Open Collections

UBC Theses and Dissertations

UBC Theses Logo

UBC Theses and Dissertations

Practical description of configurations for distributed systems management Thornton, Jim 1994

Your browser doesn't seem to have a PDF viewer, please download the PDF to view this item.

Item Metadata


831-ubc_1994-0633.pdf [ 2.32MB ]
JSON: 831-1.0051256.json
JSON-LD: 831-1.0051256-ld.json
RDF/XML (Pretty): 831-1.0051256-rdf.xml
RDF/JSON: 831-1.0051256-rdf.json
Turtle: 831-1.0051256-turtle.txt
N-Triples: 831-1.0051256-rdf-ntriples.txt
Original Record: 831-1.0051256-source.json
Full Text

Full Text

Practical Description of Configurations for DistributedSystems ManagementbyJim ThorntonB.Math (Computer Science) University of Waterloo, 1992A THESIS SUBMITTED IN PARTIAL FULFILLMENT OFTHE REQUIREMENT FOR THE DEGREE OFMASTER OF SCIENCEinTHE FACULTY OF GRADUATE STUDIESDEPARTMENT OF COMPUTER SCIENCEWe accept this thesis as conformingto the required standardTHE UNIVERSITY OF BRITISH COLUMBIASeptember 1994© Jim Thornton, 1994In presenting this thesis in partial fulfillment of therequirements for an advanced degree at the University of BritishColumbia, I agree that the Library shall make it freely availablefor reference and study. I further agree that permission forextensive copying of this thesis for scholarly purposes may begranted by the head of my department or by his or herrepresentatives. It is understood that copying or publication ofthis thesis for financial gain shall not be allowed without mywritten permission.(Signature)Department of CoMpcdfr Seit’The University of British ColumbiaVancouver, CanadaDate :30 [77tfAbstractThe administration of distributed systems is an important practical problem. One of thesignificant parts of the problem is the management of software configurations. The size andcomplexity of distributed systems have made automation of software management tasksessential. The time has come to determine how to design systems with intrinsic features thatenable general management.Experience with general approaches to software management is needed. This thesispresents a model that revolves around structured, declarative specifications of correct configurations. It is possible to use declarative specifications to automatically check the correctness of a system and also to automatically fix various problems. The model relies on anabstract view of systems as collections of objects with particular attribute values.A new language is introduced for expressing configuration descriptions abstractly. Simple processing algorithms are given for automatically comparing a system with a description, and automatically eliminating discrepancies. A prototype implementation is described,and various related issues are explored.The proposed model and language are suitable for practical use, as is demonstrated byan experiment involving a production system. While further work is needed in a variety ofareas, the feasibility of using declarative specifications according to a general, abstractmodel has been established. This approach is not of merely theoretical interest. It can beapplied to common systems in routine use today.11Table of ContentsAbstract.iiTable of Contents iiiList of Tables vList of Figures viAcknowledgment viiChapter 1 Introduction 11.1 The Management Problem 11.2 Automating Configuration Management 21.3 Existing Technology 31.4 Thesis Statement 41.5 Thesis Contributions 41.6 Thesis Scope 51.7 Outline 5Chapter 2 A Model of Distributed Configuration Management 72.1 Problem Features 72.2 Requirements 92.3 Definitions 112.4 The New Model 12Chapter 3 Managing Configurations with the Prescription Language 153.1 Introduction 153.2 Syntax 163.3 Classes and Types 173.4 Table Definition 213.5 State Descriptions 233.6 Relationship to First Order Logic 363.7 Support Functions 403.8 Repair Limitations 423.9 Repair Processing Details 443.10 Standard Class Interfaces 463.11 Example 53Chapter 4 Implementation 564.1 The Environment 56111- iv4.2 Basic Processing .584.3 Objects and Data 634.4 Prototype Classes 684.5 Distribution Facilities 734.6 Administrative Support 764.7 Issues, Limitations, and Problems 774.8 Performance 87Chapter 5 Experiment 895.1 The Specification 905.2 The Processing 965.3 Evaluation 99Chapter 6 Related Work 1046.1RCMS 1046.2Moira 1056.3 Depot 1066.4Hobgoblin 1066.SDoit 1076.6 TANIS 108Chapter 7 Conclusions 1097.1 Review of Contributions 1097.2 Future Work 111Glossary 115Bibliography 118Appendix A: Specification Details 119A. 1 Experimental Specification Definitions 120A.2 Sample Table Entries 133List of TablesTable 1: Logical Statement Operators 32Table 2: Miscellaneous Functions 41Table 3: Standard Object Methods by Group 46Table 4: StudentUolders 54Table 5: Printers 91VList of FiguresFigure 1 — File Class Hierarchy 69Figure 2 — Activation Hierarchy 80viAcknowledgmentThis thesis owes a great deal to the excellent supervision I received. Gerald Neufeld managed a remarkable balance between allowing me to follow my own path, even when hedidn’t fully understand it, and keeping me on track towards a manageable thesis. I am grateful for the opportunity he gave me to pursue my own interests in a poorly defined area, andfor his guidance that ensured the emergence of a well defined project in the end. NormHutchinson willingly gave of his time to listen to my ideas and make comments, even without any official obligation to do so.I want to give special mention to Terry Coatta, who supplied inspiration, advice, andencouragement. Terry demonstrated an unusual level of comprehension of my ramblings,which was very encouraging. Our debates helped refine my ideas at critical points.My family has encouraged me from the beginning, even though starting this program meantmoving away to the other side of the continent. Thanks also to friends, both inside and outside the University, who have helped me in various ways throughout this experience.Finally, thanks be to God, who made all this possible.vii1CHAPTER 1 Introduction1.1 The Management ProblemComputer systems require administration. A large part of that administration is managing software configurations. Software is a key component of any modern computing system. Typically,software provides a great deal of flexibility and can be adapted to many situations. Flexibilitycontributes to the power or value of software as a tool, but it comes with a price. In any particular situation, there are many details which must be exactly right in order for software to functionproperly. Many people have experienced the frustration of trying to use a system that does notfunction as it should “merely” because it is not set up correctly.Unfortunately, managing software configurations is no small task. In the first place, software isnotoriously complex stuff. A great deal of specialized knowledge is often required to configureit correctly. Simplicity of administration is not always a priority when systems are designed.Configurations are also quite fragile, so apparently small adjustments can have large effects.CHAPTER 1 - Introduction 2Dealing with continual change is also a challenge. Configuration changes must be made as people come and go, as new software is acquired and old software becomes obsolete, and as thecomputing needs of the organization change.Managing the software for a single computer is enough of a challenge, but many organizationshave computing infrastructures composed of hundreds of machines that function as a loose confederation. In these situations, it is not only necessary to configure each individual machine correctly, it is also essential to ensure that autonomous machines have compatible configurations.There is often a need to duplicate configurations as well, in order that multiple machines can beused for identical functions.Large sites typically employ skilled, professional system administrators to acquire appropriatetechnology, keep everything running properly, and support users.With hundreds of machines tolook after, however, the magnitude of the configuration task excee4s even the capacity of teamsof professionals. Since the problem is the management of advanced computing systems, it isnatural that we turn to automation and software tools for solutions.1.2 Automating Configuration ManagementRoutine configuration management consists mostly of repetitive sequences of simple operationsto configure software properly, to ensure that consistency is maintained, and to check that everything remains in proper order. These activities are ideal candidates for automation.Successful use of automation has the potential to offer a number of clear benefits to end-users.System problems may be reduced by the elimination of some human errors, and the early detection of erroneous configurations generated by human actions or faulty software. Changes in configuration, such as the installation of new software, may be able to be completed more rapidlyand more frequently, with less chance of error. More elaborate or varied configurations may beCHAPTER 1 - Introduction 3able to be supported within an organization. Ultimately, end-users may be able to safely performmore configuration operations themselves.The most effective approach to automation for the long run is not to build more and more specific tools to solve particular problems as they are encountered. Instead, we should identify thegeneral facilities and services that are required, and start building systems which include or support them. Work in this direction has begun, with the emergence of standards like SNMP [illand CMIS/CMIP [12][13], and research developments such as RCMS [4]. This thesis takesanother small step along that path, by proposing a general solution to some of the practical configuration problems associated with large numbers of workstations.The thesis deals with a particular slice of configuration management, specifically, the problemsassociated with keeping large numbers of machines configured correctly. The emphasis is therefore placed on aspects of configuration that change infrequently, such as the values of serverparameters, rather than details that change often during normal operation, such as the number ofworker threads in a server process.1.3 Existing TechnologyA variety of tools have been developed to help automate different aspects of configuration management. This thesis addresses the lack ofgenerality of many of those tools.Many tools lack generality of application. They are frequently designed to deal with only someaspects of configurations (e.g. files and directories, but not filesystem definitions or processes).A tool may impose a particular software organization that is appropriate for some sites, but notfor others.CHAPTER 1 - Introduction 4Generality of function may also be lacking. A particular tool may be designed to either set upconfigurations (the most common case), or check configurations, but not both. Those designedto do setup frequently use procedural specifications (scripts), while checkers generally usedeclarative specifications (descriptions).1.4 Thesis StatementIt is possible to automate configuration management operations ofpractical importancebased on a general model that revolves around declarative specifications. Descriptionsof correct system states may be used both to automatically check the validity of configurations, and to automatically generate the appropriate commands to bring the system inquestion into a correct state.1.5 Thesis ContributionsThe thesis makes the following significant research contributions:1. A general model is defined for describing software configurations and automating operations based on such descriptions, in a practical context. Themodel emphasizes powerful, declarative, and structured specifications.2. A new language for expressing descriptions of configurations is introduced.The Prescription language is declarative, yet at the same time it is designedso that simple, efficient algorithms can be used to discover a sequence ofoperations that may be performed to correct deviations from a specification.3. A prototype implementation is described. In the course of producing theimplementation, many issues significant to the practical use of the modeland language were discovered.4. An experimental application of the model to the configuration of realmachines at the University of British Columbia is analyzed. The trials demonstrate the feasibility of the new approach and the new language.CHAPTER 1 - Introduction 51.6 Thesis ScopeIn an area as broad as configuration management, it is not possible for a thesis such as this toaddress every issue. Unavoidably, there are significant omissions, some of which are mentionedhere by way of advance warning.The thesis is not directed towards the replacement of human administrators. In fact, the focus ison providing administrators with better technology so they can do a better job. The intelligenceand creativity required by the administration task are unlikely to be emulated by software anytime soon. There may be ways in which general search and proof techniques from computational intelligence could be applied to extend this work, but that is outside the scope of thethesis.Verification of the internal consistency of configuration descriptions is a very important topic.Constraints of space and time prevent any reasonable discussion of consistency checking.The model is demonstrated by application to a realistic, but nonetheless limited, situation. Otherareas of application need to be explored.Dynamic, automated reconfiguration is not within the scope of the thesis, though it is consistentwith the model. The task referred to here as dynamic reconfiguration is the adjustment of a system based on problems detected through monitoring or problem reporting. For instance, a routing table for an Internet router might be modified based on detection of the failure of a gateway.The emphasis here is on more static aspects of configuration.1.7 OutlineThe core of the thesis begins with the definition of the model in Chapter 2. The chapter beginswith a more detailed analysis of the problem than was included in this introduction. Factors ofCHAPTER 1 - Introduction 6size, change, complexity, diversity, repetition, and fragility are all considered briefly. A numberof requirements for a solution are derived. The model itself is then presented, beginning withdefinitions.The Prescription language is introduced in Chapter 3. All the pieces needed to realize the modelare presented. The chapter concludes with a small but complete example demonstrating theapplication of the language and model to an imaginary situation.The implementation and discoveries it engendered are described in Chapter 4. The issues andproblems presented in Section 4.7 are not all specific to the particular implementation describedin the chapter. Most are general, and relate to any implementation of the model.The final major contribution of the thesis is the experiment and analysis presented in Chapter 5.Both the model and the implementation are involved in the experiment.Other important matters are reserved to the later part of the thesis. Some related work isdescribed briefly in Chapter 6. Conclusions and proposals for further exploration are presentedin Chapter 7. An appendix provides the details of the experimental specification.7CHAPTER 2 A Model of DistnbutedConfiguration Management2.1 Problem FeaturesThe complexity of software systems of all kinds has grown to the point where humans have difficulty coping with them. The problems of size and complexity are well recognized in the software engineering domain, and also arise in the context of distributed systems management.This thesis deals with configuration management in distributed computing environments. In thepast, a large user community was usually served by a single computer. It has now become common to find networks of independent machines providing the computing resources for organizations. Each machine typically has its own operating system, local disk, and configuration. Thesediverse collections of systems are managed by small groups of people, just like the isolatedmainframes used to be.There are a number of features of distributed computing environmentswhich contribute to the management problem.CHAPTER 2- A Model of Distributed Configuration Management 8SizeA distributed computing environment features a large number of items which must be properlyconfigured. A single department may operate hundreds of machines. Each of those machinesmay have many files and directories which are local, and many references to resources on thenetwork. Even if most systems are to be configured identically, they must still be manipulatedindividually. The size problem is the basic reason why automation is essential. It is simply notfeasible for administrators to perform every configuration operation manually on each individual machine.ChangeConfigurations change constantly. Some changes are planned and significant, such as the introduction of a new machine or a new shared filesystem. Others are unplanned and may even beundesirable. For instance, someone may manually change the configuration of a system in sucha way that the system breaks. The fact of constant change has a few implications for management automation. Administrators do not have the luxury of getting everything set up correctlyonce, and then leaving it alone. Configuration management operations will be performed regularly. Also, there is more to the problem than mere setup. Administrators need to verify the configuration of systems.ComplexityDistributed system configurations become very complicated since they involve so many details.A large amount of arcane knowledge and skill is often required to properly understand andadjust configurations. The knowledge that is required consists not only of knowledge about howtechnology works, but also familiarity with various rules and conventions which are site-specific. The impact of complexity is increased when important details are either undocumented orimplicit, as is often the case.CHAPTER 2 - A Model of Distributed Configuration Management 9DiversityA number of types of diversity are significant to the problem of management. First, there isdiversity of systems. A single site is likely to have machines from different vendors, running different (or at least variant) operating systems. The prevalence of system diversity implies thatautomated configuration tools ought to be general. There is also diversity of configurationswithin a typical site. This requires administrators to keep track of which machines are configured in which ways. Finally, there is diversity across sites. Each computing environment is a little different in organization, requirements and conventions. Site diversity implies that automatedtools need to be flexible.RepetitionDistributed software configurations are highly repetitive. Consider the situation of a group ofUnix machines all accessing filesystems over a network. For each (machine, filesystem) pair,there are a number of configuration details that must be arranged correctly on the machine.Some of these details are common across all the pairs, however. Simple repetition also occurswhen machines are configured identically in some respect.FragilitySoftware systems are notoriously fragile. Small deviations from a correct state can result incomplete failure. This property is a problem in configuration as well as in programming, and itimplies that every detail is important. In fact, configuration management is all about getting thedetails right.2.2 RequirementsBased on the features just described, a number of objectives, or requirements, for any generalapproach to a solution can be identified. Some of the objectives are less than precise, due to theCHAPTER 2- A Model of Distributed Configuration Management 10nature of the problem. The model presented later in this chapter is designed to meet theserequirements:1. Automation. A solution must support as much automation as possible.2. Verification. A solution must support automated verification of the correctness of configurations. Verification addresses the problems of fragility andchange management. Automation in this area requires some way to specifythe correct configuration of a machine.3. Declarative form. A configuration management system should be designedto use declarative specifications to the greatest extent possible. Declarativespecifications are easier to understand and reason about than scripts or programs, when the objective is specification of states rather than computation.A declarative form will minimize complexity and simplify automated verification. A declarative form also partially addresses the problem of systemdiversity, since it avoids the difficulties of different execution environmentson different machines.4. Abstraction. A solution needs to be abstract in order to generalize to manydifferent types of systems. Idiosyncracies of syntax that are particular tocertain systems should be avoided. The use of abstraction can also serve tolimit complexity.5. Flexibility. Any configuration management system needs to be flexible inorder to cope with the diversity of configurations and diversity of sites. Aspecification formalism should be powerful enough to describe any configuration state. In addition, it should not impose a particular system organization.6. Structure. A model must support structure in configuration descriptions.Appropriate structure can minimize repetition, and help people deal withthe complexity of diverse configurations.7. Synchronism. An automated system needs to keep systems synchronizedwith changing specifications, to avoid the problems associated with changeand fragility.CHAPTER 2- A Model of Distributed Configuration Management 118. Transparency. A model must provide for specifications which are as explicitand self-documenting as possible. Transparency helps reduce complexity.In addition to the requirements based on problem features, there is one final requirement thatmotivates the design of the model presented in this thesis:9. Practicality. The solution must be appropriate for practical use in managingnon-research distributed systems.2.3 DefinitionsA few terms are central to the new model.A managed system is a collection of related entities whose configuration is managed with automation. The entities may be hardware or software, but software is the focus of the thesis. Theentities that comprise a managed system are not restricted to a single machine. A managed system will be assumed to include a network, the machines on the network, and all of the softwareentities existing on all of the machines.A component is any distinguishable piece of a managed system. For instance, files, directories,entries in tables, ports, sockets, and processes are all components of a managed system containing Unix machines. It is important to note that component always refers to an actual piece of amanaged system, in contrast to the term object, which is defined next.An object is an abstraction which represents or models a component. As an abstraction, anobject presents certain features of the component it models, but not every feature. In particular,an object represents the configuration state of a component. Various aspects of the state of acomponent are represented by values of attributes of the modelling object. For instance, anobject that models a file will have attributes for size, permissions, and so forth. The object willnot model the operations that can be performed on a component (such as open in the case of aCHAPTER 2- A Model of Distributed Configuration Management 12file). Any operations that are associated with an object are configuration management operations.2.4 The New ModelA new approach to a practical configuration management system is presented here, based on theobjectives listed in Section 2.2. At the centre of the new model is the idea that any configurationstate of a managed system may be viewed as the union of the states of a set of objects representing components in the system1. A specification of a configuration consists of a declarativedescription of the states of a set of objects. Such specifications are the basis for all automatedconfiguration management operations. The automated procedures of interest are comparison ofspecifications with actual managed systems, identification of discrepancies, determination ofsequences of operations which may be performed to eliminate the discrepancies, and executionof the operations.Through the use of objects, the model meets the abstraction and flexibility objectives of Section2.2. Objects, as defined earlier, are abstractions that can be used to represent many differentkinds of components. A specification language based on objects requires only one uniform syntax. Tools built according to this model are inherently flexible because the primary functionalityis based on general abstractions, rather than the peculiarities of certain types of components.It is not obvious that the new model can satisfy the conflicting requirements of automation, verification, and practicality. The majority of the thesis is devoted to showing that the use of declarative specifications does not preclude practical automation.There are two parts to the model, each of which will be described separately. The specificationpart prescribes a particular structure for descriptions of configurations, and addresses the1. This is the basic idea behind the general model introduced in [4].CHAPTER 2- A Model of Distributed Configuration Management 13requirements for declarative form, structure, and transparency. The automation part prescribes aparticular approach to software tools, and addresses the requirement for synchronism.2.4.1 SpecificationSpecifications of configurations (also called descriptions) have two parts. One part consists of aset of parameterized descriptions of object states, written in a simple logic language. The otherpart consists of a collection of data in a simple relational database. The database entries are referenced in the parameterized descriptions.The logic language must be amenable to two different types of automated processing. The process of comparing a managed system with a specification is called verification, and a declarativelanguage is naturally well suited to it. As mentioned earlier, however, automated proceduresmust also be able to generate, and execute, a sequence of operations to bring a managed systeminto conformance with a specification. This second process is called repair.The database part of configuration descriptions is important for structural reasons. A logic language may supply descriptive adequacy, that is, it may permit any configuration state to bedescribed. A language alone, however, does not provide enough structure to avoid repetition.The example of shared filesystems is helpful at this point. On each machine that imports a filesystem, a certain configuration must exist. Many details should be common across filesystems,but there are also details that are unique to each particular filesystem. For example, the mountpoint directory might be placed in /nfs and given the name of the filesystem, by convention. Inthat case, only the name of the required directory varies between filesystems. The name is anexample of instance data. The mount point directory should be described only once in a specification, with the filesystem name as a parameter. A simple database table is a convenient formfor the presentation and manipulation of instance data values.CHAPTER 2- A Model of Distributed Configuration Management 14Flexibility in this two-part specification form is achieved by leaving the definition of databaseschema and the creation of descriptions in the logic language up to administrators. The genericdescriptions define the organizational structure and explicitly incorporate local rules and conventions. The database contains only the details which vary, separated from the repeated details.The Prescription language, presented in Chapter 3, is designed to balance the need for declarative power with the requirement for practical repair. The language also supports modularity, topermit structuring and repetition avoidance, and in-line comments, to enhance transparency.2.4.2 AutomationThe basic principle of the model concerning automation is that all automation revolves aroundspecifications. A variety of specific tools are possible. For example, a tool could be created toexamine part of a managed system and produce a specification that describes the configuration.In order to maintain synchronism of a distributed system with changing specifications, a configuration management system must be designed to operate continuously, and not just at infrequentintervals. For instance, adjustments to a machine configuration must not be delayed until themachine is next rebooted. The configuration management system must have regular access tomachines in the managed system.The majority of the software that performs automated processing based on specifications shouldbe designed to operate on objects through standardized methods, in order to maintain the generality benefits of the abstraction. The implementation of the methods must manipulate real components, providing a translation between the object abstraction and the component reality. Theissues associated with such a translation are extensively explored in Chapter 4.15CHAPTER 3 Managing Configurations with thePrescription LanguageThis chapter presents the Prescription language, which is designed to be used for describingsoftware configurations for management automation, consistent with the model introduced inthe previous chapter.3.1 IntroductionThe Prescription language is a tool for realizing the new model. According to that model, allmanaged components are abstractly represented as objects with attributes. The entire configuration state of a component is assumed to be represented by the values of attributes associatedwith an object. A specification consists of entries in some tables plus some logic descriptions ofobject states, in terms of the data in the tables. In order to meet the flexibility requirement of themodel, there are actually three functions which the tool set must support:1. Definition of object classes to model the various types of components2. Definition of tables which will contain instance dataCHAPTER 3- Managing Configurations with the Prescription Language 163. Description of object statesThis chapter deals with each of the three functions separately, in order. The chapter concludeswith a short example that combines all the pieces.The heart of the Prescription language is the set of statements for describing object states. Thesestatements involve only the object abstraction, since even the contents of tables are modelled byobjects. The situation is not nearly as simple for table and class definitions. Table definitionsmust refer to specific files that will hold the data, and class definitions must be related to implementations which map the object abstraction to the component reality. For these functions,therefore, the details presented in this chapter will be partly dependent on the nature of the prototype implementation.3.2 SyntaxThe Prescription language could be implemented using any one of a myriad of syntax styles,from a Pascal style, to a C style, to a LISP style. A good syntax for the language would be clean,simple, and relatively terse. The ideal style would be one with those characteristics and somegeneral appeal to the user community. The style used in this thesis is determined by the implementation.Here are the main points which are important for understanding the examples:1. A text consists of sequences of statements, one per line. The backslash (\)serves as a continuation character, and the semicolon (;) may be used toseparate statements written on the same line.2. Braces ({ and }) are used for grouping. For this reason, blocks of statementscan be written to appear like blocks in C.3. The string is the basic data type, and string literals do not need to be quotedunless they contain whitespace characters. Either double quotes (“) orCHAPTER 3- Managing Configurations with the Prescription Language 17braces may be used to quote strings1.The following two strings are identical:“Hello World” {Hello World}4. In order to use the value of a variable, the name of the variable is precededby a dollar sign ($). This convention is similar to that used in BASIC.5. Comments begin with an octothorpe (#) and end at the following line break.6. The value returned by a function may be used in-line by enclosing the command in square brackets ([and 1).7. A global variable may be accessed within a local scope if the name of thevariable is given as an argument to the global command, as illustratedbelow for the variable Window:global Window8. Assignment to a variable is performed by the set command. The followingcommand assigns the value 14 to the variable abra.set abra 143.3 Classes and TypesEvery object is an instance of a particular object class, as in standard object-oriented practice.Object references may be assigned to variables, so the definition of a class also introduces a typeof the same name as the class2.There are also fundamental types such as Integer.Each class defines the object abstraction for a particular type of component. An associatedimplementation performs the mapping between the abstraction and the managed system. In thecontext of the Prescription language, a managed system is defined by the set of object classesthat are defined. The descriptive statements, and the processing algorithms associated with1. There two quoting forms differ as to the treatment of embedded variable references. The distinction isnot important at this point.2. The prototype implementation supports very little type checking. For this reason, types will not appeareverywhere they should in the examples. A production implementation would benefit significantly fromstatic type checking.CHAPTER 3- Managing Configurations with the Prescription Language 18them, are not restricted to describing files and directories. They can be used with any kind ofmanaged system, as long as the appropriate classes are defined and implemented. This generality is the benefit gained from the object abstraction.The class structure can be described briefly using standard terminology. Single inheritance issupported, and multiple inheritance is unnecessary. Class methods are supported, but no needfor class objects or meta-objects has been identified. Inheritance is not used for class methodlookup. In order to support the algorithms for processing state descriptions, a class must exportstandard interfaces; additional interfaces may be defined by the creator for implementation use.The standard interfaces will be described later. There is a predefined base class called Object,with appropriate default implementations of many of the standard interfaces. Container classesare explicitly distinguished from non-container classes. The details of class structure, apart fromthose mentioned above, are not significant.In addition to the types associated with object classes, there are also fundamental types, as hasbeen mentioned. The Integer, Real, String, and List types do not have class definitionsor implementations. The Integer and Real types support common operations on numericvalues. The String type is used for regular character strings, supporting operations such asconcatenation. The List type is a simple homogenous aggregate type. A List declarationmust include the type of the elements in the list.3.3.1 Definitional StatementsA class is defined by a statement with the following form1:class name parent contents clef-block1. In these syntax templates, parameters for which actual values must be supplied are set in slanted characters.CHAPTER 3- Managing Configurations with the Prescription Language 19The name parameter is the name of the class. The parent parameter is the name of the parentclass in the inheritance hierarchy. The contents parameter is the type of items contained ininstances of the class. For non-container classes, a null string must be supplied as the con —tents parameter. The def-block is a block containing the attribute and method definitionsfor the class.Attributes are defined as follows:attribute name type qualifiersThe name parameter is the name of the attribute, which must be used in attribute references.The type parameter specifies the type of the attribute value. The qualifiers parameter isused to identify important characteristics of the attribute. For instance, an attribute might bemarked as immutable.Methods can be defined by name and formal parameter list. Implementations must be providedfor each defined method, but the mechanism for doing so is an implementation detail, and istherefore beyond the scope of the Prescription language. It is assumed that conventional per-class instance data will be supported for each object.3.3.2 Object and Attribute ReferenceInitially, object references are obtained from definition statements. Thus the object for a tablethat forms part of a specification is obtained from the table statement, as illustrated in the nextsection. Object references may be assigned to variables. An attribute reference consists of anobject reference, a period, and an attribute name, following the syntax of structure-member reference in Pascal or C. For example, the following reference is to the number attribute of theobject contained in variable Q:numberCHAPTER 3- Managing Configurations with the Prescription Language 20Attributes may have values of a fundamental type, or may be object-valued. Due to the secondpossibility, multi-part attribute references may be generated, using the syntax of nested structurereference in Pascal:$F. son.heightIn this case, the value of the son attribute of the object referenced by F is an object having anattribute height1.3.3.3 ExampleThe following is an example of class definition. Two classes are defined. Sample method definitions are not provided, as they are beyond the scope of this chapter.class Carton Object U {attribute name String immutableattribute size Real Uattribute colour String {}class Wagon Object Carton {attribute name String immutableattribute first Cartonattribute owner StringThe first class (Carton) inherits from Object and has three attributes: name, size, andC 01 our. It is not a container class, since the null string is supplied as the contents parameter. The name is of type String, and is declared to be immutable. The colour is also of typeString, but has no special declarations. The size is of type Real.The Wagon class is a container class. Any instance of Wagon contains objects of class Carton. Note that Wagon also has an object-valued attribute (first, of type Carton).1. Note that only one dollar sign is required; we do not write $($F.son).height. The dollar sign specifiesvariable dereference, not object dereference, which is always performed implicitly. This peculiarity ofsyntax is a product of the prototype implementation.CHAPTER 3- Managing Configurations with the Prescription Language 213.4 Table DefinitionThe database part of a configuration description consists of a set of tables which form a simplerelational database. For each table in a database, a certain amount of information is required inorder to permit it to be used in a specification. The necessary information is supplied by a definition statement of the following form:table name filename field-delimiter fields-list key subtables-listThe name parameter supplies the name of the table. The filename is the name of the filewhich contains the records in the table, with fields delimited by the field-delimiterstring. The fields-list is a list of field definitions, each consisting of a field name and a declaredtype. The key parameter identifies a primary key by listing the names of the fields which compose the key, in order. The key parameter may also be empty, in the case of a table with no primary key. The subtables-list identifies tables which are sub-tables, and includes informationdescribing the relationships. A sub-table is a table which may contain multiple records associated with each record in the primary table. The sub-table information is not essential for configuration management, but indicates the structure of the database, and can be used by browsingtools.Here is a sample table definition:table MachineGroup mgroup.table I { \(name String} \(subgroups List MachineGroup} \(members List Machine} \(name} 0The name of the table is MachineGroup. The file from which records will be read ismgroup. table. Fields in that file are declared to be delimited by vertical bar characters, asindicated by the third parameter. The table has three fields, called name, subgroups, andmembers. The name field is of type String. The other two fields are both of List types. InCHAPTER 3- Managing Configurations with the Prescription Language 22the case of subgroups, a List of MachineGroup, and in the case of members, a List ofMachine. The file mgroup. table must contain strings representing every field value. Whenan field is of an object type, the string used to represent a value is a foreign key identifying a particular object. In this example, there are no sub-tables, so the empty string is supplied as the finalparameter. The MachineGroup table defines a graph of groups (intended to be. a tree in practice).A table definition causes a number of things to be done implicitly. First, a class is defined for thetable. The name of the class is the name of the table with the string “Table” appended. The newclass inherits from a standard class called simply Table, and is a container class. The objectscontained in an instance of a table class represent individual records in the table. A tablestatement, therefore, also causes the definition of a class for those contained objects, with anattribute corresponding to each field. The name of this new class is the same as the name of thetable. A table statement also causes the creation of an object to represent the table (aninstance of the new table class), and the creation of objects to represent each record in the table.The object representing the table is generally assigned to a variable. Thus the previous exampledefinition would normally be written something like the following:set MGroups [table MachineGroup mgroup.table I ( \(name String} \{subgroups List MachineGroup} \(members List Machine} \} (name} {} IAs a result of this statement, a class named MachineGroup would be implicitly defined forobjects representing records from the file mgroup. table. A class named MachineGroupTable would also be implicitly defined as a container class containing objects of classMachineGroup. An instance of this second class would be created and its reference would beassigned to the variable MGroups. Finally, the contents of file mgroup. table would be readCHAPTER 3- Managing Configurations with the Prescription Language 23and objects created for each record (each an instance of class MachineGroup). The tablestatement plays the role of the new statement in other object-oriented environments.When a field has an object type, the values actually stored in the table file for that field are foreign keys. The class created for records in a table automatically translates a foreign key into theappropriate object when the attribute for such a field is referenced. In some situations, the foreign key value itself is required, rather than the object. To accommodate these circumstances, aspecial variant syntax for attribute reference is provided. The prepending of an @ symbol to anattribute name specifies that the key value is required, not the object identified by the key value.This syntax is illustrated by the following example:$F. sonAs the tables are modelled by objects, the descriptive statements that will be introduced shortlymay be used to express specifications of constraints on the tables. Since the tables are considered part of the specification, the prototype implementation does not support any automatedrepair of them. Repair could be supported, however.The definition of the database schema and the creation of records in the database are both theprovince of the administrators responsible for the managed system. The format of record storageand the mechanisms used for editing records are beyond the scope of the specification language,and are implementation-specific. The prototype uses text files with simple structure, but a complete RDBMS is equally possible.3.5 State DescriptionsThis section covers the heart of the Prescription language, namely those statements and featureswhich are provided for the description of object states. The descriptive statements that will bepresented here are designed to be used for the structural parts of configuration specifications.CHAPTER 3 - Managing Configurations with the Prescription Language 24The descriptive statements are inherently declarative, each expressing a description rather than adirective. Each statement may be easily evaluated against a managed system at a particular pointin time, to determine whether or not the described state holds. Each statement, therefore, has atruth value when considered relative to a particular managed system.Although the language is declarative, there are also simple processing algorithms associatedwith each kind of descriptive statement. For each statement, there is a procedure for determininga truth value. In many cases, there is also a repair algorithm. A repair algorithm is a procedure toefficiently compute a sequence of operations which could be performed to modify the state ofthe managed system so that a statement would evaluate to True.In order to facilitate state descriptions, the object model must be elaborated slightly. Someobjects are collections which contain other objects. The list, or set, of contained objects is anattribute of the collection object, but it is an attribute of special significance. A number of thedescriptive statements reference the contents of a collection object implicitly.For practical specifications, facilities for general computation are important. General functionsare used for the generation of values from other values (e.g. string concatenation, simple arithmetic). The set of general functions, and the mechanism for defining new ones are implementation dependent. The only restriction is that general functions must never manipulate themanaged system. If they were to do so, the specifications would no longer be declarative, andimplementation problems would arise.The Prescription language is analogous to traditional programming languages in a number ofways. Statements may be grouped in block structures. Modularity is supported through named,parameterized blocks of statements like traditional procedures. Variables are used in exactly thesame fashion as in conmion imperative languages supporting call-by-value.CHAPTER 3- Managing Configurations with the Prescription Language 253.5.1 PrescriptionsThe unit of definition in the language is the prescription. A prescription is a named block ofstatements, with a list of named formal parameters which are used in the block as local variables. A prescription serves as a modular description of part of the configuration of a managedsystem.A prescription plays a role similar to that of a predicate in a logic programming language likeProlog. If the formal parameters are bound to particular objects, the predicate has a truth value.There is not, however, any facility for automatic selection of values for unbound variables, as isprovided in Prolog. In operational terms, a prescription plays the role of a procedure in a language like Pascal. In recognition of the special nature of prescriptions, they are said to be activated, rather than called as procedures.Prescriptions are defined in a global scope in a fashion very similar to function definition in C.The following is an example of the definition of a prescription with an empty block as the body:prescription FirstOne (a b ci {In this example, the name of the new prescription is Firs tOne, and there are three formalparameters, named a, b, and c. Prescriptions may be defined to be narrowed by the addition ofthe keyword -narrow1after the keyword prescription. Narrowing affects processing in away that will be explained as soon as the processing modes have been described.1. The hyphen is part of the keyword, and marks it as an option switch.CHAPTER 3- Managing Configurations with the Prescription Language 26Prescriptions may be activated in a fashion similar to traditional procedure call. Actual parameter values must be supplied for each formal parameter. In the following example, the prescription SecondOne contains a single statement which is a recursive activation of the prescription.prescription SecondOne {a b} {SecondOne $a $b}Note that prescription activation follows the syntax of statements, in which arguments are separated by spaces. While recursion is legal, this particular prescription is nonsensical from a logicpoint of view, and could not be processed without error.3.5.2 Processing ModesPrescriptions may be processed in two ways, described as separate processing modes. In verifymode, the sole objective of processing is to determine the truth value of a description at a pointin time. In repair mode, an additional requirement is added; the managed system must be modified to conform to the description if possible.The central principle of all Prescription processing is minimality. Evaluation of a prescription,or a statement, terminates as soon as the truth value has been determined. This is the same strategy used in the evaluation of expressions in C. Another consequence of minimality is that processing never results in modifications to the managed system in verify mode. In repair mode,modifications may be made, but the set of modifications is always minimal. If a prescriptiondescribes the existence of a particular file with certain permissions, and the file exists with different permissions, the only change made during repair mode processing will be a change to thepermissions of the file.The processing mode is normally preserved across prescription activations. Overriding of theprocessing mode is possible through narrowing, which is explained in the next section.CHAPTER 3- Managing Configurations with the Prescription Language 27Not every descriptive statement is amenable to automated repair. Some statement forms do notinclude enough information to automatically select a repair algorithm. The reason such formsare tolerated in the language is that they have descriptive value. A statement for which there is arepair algorithm is designated as repairable. Note that repair may fail for a statement that is formally repairable, because the availability of an algorithm does not guarantee that the algorithmcan be successfully applied. In verify mode, all statements can be processed, but in repair mode,processing of non-repairable statements might generate an error.3.5.3 NarrowingIn various situations the full descriptive power of the language is required, and automated repairis either unexpected or undesirable. For example, a constraint may be expected to hold, withhuman notification required if it does not. It is desirable to be able to place such constraints inregular prescriptions that may be subject to repair processing. In these situations, the prescription author needs a way to selectively disable automated repair. Restriction of the processingmode to verify mode is called narrowing. A narrowed statement or prescription is always processed in verify mode, regardless of the mode in effect in the containing block. The restriction toverify mode is preserved through nesting and prescription activation.There are two forms of narrowing. Individual statements may be narrowed with explicit syntax,as described in the next section. Alternatively, a prescription may be defined as narrowed, asdescribed in Section 3.5.1, which causes every activation of that prescription to be narrowedautomatically.Although it is of practical importance, narrowing does not affect the logical meaning of statements at all. It merely affects repair processing.CHAPTER 3- Managing Configurations with the Prescription Language 283.5.4 BlocksAs in many programming languages, Prescription statements are grouped in blocks. Unlikeother languages, the blocks themselves have logical semantics. There are three types of blocks:And blocks, Or blocks, and Narrow blocks.Blocks are themselves legal statements, and so may be nested inside each other. There are different syntax possibilities for representing the distinction between block types. Different delimiterscould be used for different types of blocks. In the syntax used here, braces delimit blocks of alltypes, and block statements are introduced by a keyword that identifies the type.Statements are processed in order of occurrence, subject to the principle of minimality describedin Section 3.5.2. The reason for order significance is to make processing easier to understand,and prescriptions simpler to write. A consequence is that implicit dependencies based on ordermay exist between statements.And BlocksAn And block has the value True if and only if each contained statement has the value True.Thus an And block represents the logical AND of the statements in the block. The followingexample block always has the value True (the true and false statements always have thevalues True and False respectively):andtruetrueThe following block has the value False in all cases:and ftruefalseCHAPTER 3- Managing Configurations with the Prescription Language 29Both And and Or blocks are repairable. The body of a prescription is always an implicit Andblock. An And block may be empty, in which case it has the value True.Or BlocksAn Or block has the value True if and only if there is at least one statement in the block whichhas the value True. Thus an Or block represents the logical OR of the contained statements. Thefollowing block has the value True in all cases:or ffalsefalsetruefalse}In accordance with the minimality principle, processing of an Or block terminates as soon as thetruth value is determined. This pattern holds in both verify and repair modes. Repair mode processing involves two phases. First, the block is processed in verify mode, as though narrowed. Ifthe block has the value False, implying that repair is required, each statement is then processedin turn in repair mode, until repair is successful for some statement. At that point, processing ofthe block terminates. Should repair fail for all statements, the block terminates with the valueFalse.Narrow BlocksA Narrow block is used to specify narrowing. Narrowing is intended to be applied to singlestatements1.The following example block has the value False in all cases, but automated repairwill never be attempted on any of the statements.narrow { and {truetrue1. For implementation reasons, a block is used. If multiple statements are included in the block it has thevalue of logical AND.CHAPTER 3- Managing Configurations with the Prescription Language 30false3.5.5 If StatementsAn ± f statement is defined, for expressing configurations conditionally. The statement has thefollowing form:if { expression } then-block ?else-block?1The expression part is just a standard boolean expression which may be composed of variable references, operators and functions. When the expression has the value True, the entirestatement has the logical value of the then—block. Otherwise the statement has the logicalvalue of the else-block if present, and the value True if not. In the following example, theif statement has the value True:if { 1 == 1 } {true} else {false}When an if statement is processed, the expression is evaluated first, then the appropriateblock is processed. The if statement is repairable.3.5.6 Logical StatementsA logical statement describes the state of a particular object by describing the value of one of theattributes of the object. A logical statement may or may not be repairable, depending upon theparts that are included. The statement has the following form:logical ?attribute-reference? ?op? expression1. In these syntax templates, optional parts are enclosed in question marks.CHAPTER 3- Managing Configurations with the Prescription Language 31The attribute-reference parameter is a reference to an attribute of a particular object,through a variable. The op parameter is the comparison operator used to relate the attributevalue to the value given by the expression. For example, the following logical statementstates that the value of the count attribute of the object referenced by the variable a is 1:logical $a.count 1The value of the logical is the value obtained by applying the op to the attribute value andexpression. When the statement is processed, the expression is evaluated, the attributevalue is obtained, and the appropriate comparison is performed. If repair is required, a suitablevalue is determined for assignment to the attribute. In some cases, the value to assign is triviallyobtainable, as in the above example. Other operators make determination of a suitable repairvalue more difficult.The attribute—reference and op parameters are optional. If they are omitted then thelogical is non-repairable, because it does not include any identification of a particular piece ofthe managed system that can be modified. In the non-repairable case, the expression must evaluate to a logical value, which becomes the truth value of the entire statement. Here is the sameconstraint as in the previous example, expressed in non-repairable form:logical Li {} {$a.count == 1)Note that empty strings, delimited here by braces, are supplied for the first two parameters.Logical Statement OperatorsA wide variety of operators are possible, but only a few have been implemented in the prototype. Those that have been implemented are summarized here. Note that the presence of sepaCHAPTER 3 - Managing Configurations with the Prescription Language 32rate operators for testing numbers and strings is due to the limited typing system of theprototype implementation.Table 1: Logical Statement OperatorsOperator Description== Numeric equality! = Numeric inequality< Numeric less-than> Numeric greater-thans = String equalitys ! = String inequalitys< String less-than (lexicographic)s> String greater-than (lexicographic)contains Membership in collectioneq Deep object equalityFor these operators, there are repair algorithms that can be invoked when the value of anattribute causes the relation to be False. There may not be a repair algorithm for every imaginable operator. The statement can only support operators for which there is a possibility of repair.3.5,7 ForaIl StatementsThe foral 1 statement describes the configuration of a set of objects. The form of the statementis as follows:forall var Lype ?-closure? collection ?constraint? blockThe var parameter is the name of a variable, whose type is given by the type parameter. Thecollection parameter is an object which contains the objects the statement is about. Theoptional constraint is an expression in terms of the variable var, which identifies the par-CHAPTER 3- Managing Configurations with the Prescription Language 33ticular objects from collection that the statement is about. The block contains statementsthat describe a configuration of each selected object, in terms of var. The block here is animplicit And block. The optional —closure flag specifies that the statement is about all objectsin the closure of the collection under containment. Specification of the closure of a collection is useful for hierarchical structures such as Unix directory trees. In the following example,the statement describes a configuration in which the count attribute of each object in the collection identified by variable col has the value 1.forall v Vooble $col } {logical $v.count == 1The value of a forall statement is True if and only if the value of the body is True for everyobject satisfying the constraint (if supplied) and contained in the collection (or itsclosure, if specified). The type of the variable (Voobl e in this example) serves as an implicitconstraint. A collection may contain objects of different specific classes, although they are allinstances of the same base class. The variable type is used to constrain the statement to objectsof a particular sub-class.The forall statement is processed by successively binding the objects in the collectionto the variable var (defined in the scope in which the statement resides). If a constraint issupplied, then it is evaluated for each object, and those for which it evaluates to False areskipped. Those objects which are not of the specified type are also skipped. If the closure of thecollection is specified, then objects are retrieved from collection objects hierarchicallycontained in the specified collection. For each selected object, the body block is processed. If the block evaluates to False for some object, the truth value of the statement isknown, so processing terminates (unless repair mode is in force and repair is successful). Theforal 1 statement is repairable.CHAPTER 3 - Managing Configurations with the Prescription Language 34Optimization using the ConstraintThe constraint parameter primarily serves a semantic role, but may be used to increase efficiency. Semantically, the constraint is used to select particular objects to which the block is toapply. In the interest of efficiency, the presence of a selection criterion may permit the statementto be processed without iteration through all candidate objects. Instead of blindly iterating, itmay be possible to narrow the search space or even retrieve an appropriate sub-collection,depending on the nature of the collection.3.5.8 Require StatementsA require statement describes the configuration of an object which must exist in a collection.The form is as follows:require var type ?id? ?-closure? collection blockThe var, type, collection, and -closure parts are identical to the corresponding partsof forall. The optional id is a value which uniquely identifies an object from the collecti on as the one which the statement asserts must exist. It can be viewed as a key, and couldhave multiple parts. The nature of the identifying value is dependent on the collection ingeneral, but when the closure is specified a particular form must be used. That form is a paththrough the hierarchy, with each component identifying an object in a collection at a differentlevel. In the prototype implementation, such a path is expressed in the syntax of Unix pathnames. Thus the following example describes the configuration of a file referenced relative tothe directory identified by variable dir:require F File /sub/one -closure $dir {logical $F.perms == 0755CHAPTER 3- Managing Configurations with the Prescription Language 35A require statement has the value True if and only if there is an object in the collection(or its closure, if specified), identified by i d (if supplied), for which the block has the valueTrue. In the absence of an id value, there may be multiple objects for which the block has thevalue True. As in forall, the block is an implicit And block.The processing algorithm used with require depends on whether an id value is supplied.With an object identification, processing begins with a search for the identified object. If it doesnot exist, the statement has the value False. If the identified object does exist, then it is bound tothe declared var and the body is processed. Without an object identification, the variable issuccessively bound to the objects in the collection, until one is found for which the block evaluates to True.A require statement is repairable only if an identification is supplied. The identification indicates precisely which object the statement is describing, and so enables automatic determinationof the problem that is the cause of a False value. The two possible problems are:1. The required object is absent from the collection.2. The required object is present but is not correctly configured.In case of the first problem, the repair action is to create the object in the collection with defaultvalues for attributes unrelated to identification. The situation then reduces to the second problem, which is handled by simply processing the body in repair mode.3.5.9 Disallow StatementsA disallow statement describes objects that must not exist in a collection. The form is as follows:disallow var iype ?—closure? collection ?constraint? blockCHAPTER 3- Managing Configurations with the Prescription Language 36The parts of the statement are all identical to the corresponding parts of the foral 1 statement.The difference is in the meaning of the statement. For example, the following statementdescribes a configuration in which there are no objects in the collection identified by variablecol with size 5:disallow v Vooble $col {logical $v.size 5}A disallow statement has the value True if and only if there is no object in the collection(or its closure, if specified) for which the block has the value True. Once again the block isan implicit And block.Processing proceeds as with the torah statement, except that the truth value is known as soonas the first object is found for which the body is True, rather than False.For repair, the same difficulty arises with disallow as with require; a repair strategy mustbe selected. For disallow, however, the same strategy is always used. Offending objects(those for which the body has the value True) are always destroyed. In a situation where destruction would be inappropriate, the statement should be narrowed and offending objects should behandled manually.The meaning of “destruction” in the above description is flexible, because it is dependent on theimplementations of object classes. For instance, destruction might be equivalent to Unix unlink,which may destroy only a reference to an item, and not the item itself.3.6 Relationship to First Order LogicThe Prescription language is, in essence, a logic language. It is derived from first order logic.The differences are due either to the goal of supporting automated repair, or to practical considCHAPTER 3- Managing Configurations with the Prescription Language 37erations. The relationships between the various descriptive statements of the language andexpressions of first order logic are described here. This section can be safely skipped if the theoretical details are not of interest.3.6.1 BlocksThe relationship between Prescription blocks and simple logic constructs is very straightforward. An And block is equivalent to the conjunction of the contained statements, while an Orblock is equivalent to the disjunction of the contained statements.Notably, there is no Prescription equivalent of simple negation. This is due to the problem ofautomating repair. Negation is possible in expressions, and the effect of negation can sometimesbe achieved by selection of the correct logical operator. Also, the disallow statement isrelated to negation.3.6.2 ForalIThe foral 1 statement is equivalent to universal quantification in first order logic. The translation is quite straightforward. A statement of the following form:forall x XType $col { E(x) } { A(x)(where E(x) is an expression involving x and A(x) is a statement involving x) is logically equivalent to the following expression in first order logic:V x E $col, ( x ° XType A (E(x)) ) (A’(x))where o f3 means that x is type conformant to type f3, and X’ indicates the expression in firstorder logic which is equivalent to the prescription statement X. Similarly, a statement of the following form:forall x XType -closure $col { E(x) } { A(x) }CHAPTER 3- Managing Configurations with the Prescription Language 38is equivalent to the following expression:V x C closure($col), ( x XType A (E(x)) ) (A’(x))where closure (q) is the closure of q under containment.Note that the fora11 statement is structured to explicitly separate the left side of the implication from the right side.3.6.3 RequireThe require statement is equivalent to existential quantification in first order logic. A statement of the formrequire x XType id $col { A(x) }is logically equivalent tox C $col ( x XType ) A (x — id) A A’(x)where x — means that x is uniquely identified by I. Similarly, the closure formrequire x XType id —closure $col { A(x) }is equivalent to3 x C closure($col) I ( x 0 XType ) A (x -— id) A A’(x)Note that the require statement distinguishes particular parts of the expression (the type andidentity constraints). The distinguished parts provide enough information to enable automaticselection of the correct repair strategy. The statement may be written without an identifyingvalue:require x XType {} $col { A(x) }CHAPTER 3- Managing Configurations with the Prescription Language 39which is logically equivalent tox e $col I ( x ° XType ) A A(x)3.6.4 DisallowThe disallow statement is equivalent to negation of existential quantification. Therefore, astatement of the formdisallow x XType $col { E(x) } { A(x) }is logically equivalent tox E $col I ( x ° XType ) A E(x) A A’(x)The closure formdisallow x XType -closure $col { E(x) } { A(x) }is equivalent to—‘ x E closure($col) I ( x ° XType ) A E(x) A A’(x)3.6.5 LogicalThe relationship between a logical statement and an expression in first order logic is verysimple. A logical of the following formlogical $a.b.c A v(where A is any operator) is logically equivalent to$a.b.c A vIn the non-repairable form, the statement is simply equivalent to the expression part.CHAPTER 3- Managing Configurations with the Prescription Language 403.6.6 ItThere is also a very simple relationship between an if statement and an expression in first orderlogic. A statement in the following formif { E } f A }is logically equivalent to the following expressionE A3.6.7 DerivationThe statements of the Prescription language were actually derived based on first order logicexpressions. Each statement can be considered to express a useful idiom of logic in a mannerintended to facilitate specifying configurations and performing automated repair.3.7 Support FunctionsAs indicated in Section 3.5, general computation functions are required. Some of the significantfunctions implemented in the prototype are described briefly here.3.7.1 Membership TestingIt is frequently necessary to test a collection for the presence of a particular object. For this purpose, the boolean-valued function in is provided:in ?-key? val collectionThere are two forms of membership testing. Without the —key switch, a simple test for the presence of the object val in the collection is performed. When the -key switch is supplied,the val parameter is taken to be an object identifier like that used in the require statement.The function then returns True if and only if there is an object in collection identified byval.CHAPTER 3- Managing Configurations with the Prescription Language 413.7.2 String ConcatenationThe most common value manipulation is the production of string values by concatenation. Inmany implementations, string concatenation would require an explicit function. In the prototypeimplementation, no special function is required. For example, the following string is the concatenation of the value of variable a, a stroke character (/), and the value of variable b:$a/$b3.7.3 Special PurposeA number of special functions are used in the prototype implementation. In another implementation, operators might handle these cases. The functions are summarized in the following table:Table 2: Miscellaneous FunctionsFunction Form Descriptionval aref Returns the value of an object attribute. Thedesired value is identified by an attribute referencearef. This function is only required in certain situations, due to the nature of the implementation.obj EQ a b Boolean function which tests two objects (referenced by a and b) for identity.globEQ pattern b Function to test a string b for a glob match againstthe patternstrEQ a b Convenience function to test two strings (a and b)for equalitystrNE a b Convenience function to test two strings (a and b)for inequalityCHAPTER 3- Managing Configurations with the Prescription Language 423.8 Repair LimitationsThe Prescription language has considerable descriptive power. Despite the fact that it isdesigned to support automated repair, there are many configuration descriptions that can be written for which repair will not be successful. Each major barrier to repair is presented briefly here.3.8.1 Explicit NarrowingAs described earlier, it is possible to write pieces of description for which repair is inhibited.This may be done whether or not the narrowed statements are repairable.3.8.2 Implicit NarrowingWhen a non-repairable statement is encountered during processing, it may be implicitly narrowed. This is the case with the require statement when the key value is omitted.3.8.3 Solver InadequacyRepair always proceeds in a simple fashion without backtracking. As a result, there are specifications for which repair will fail to produce a correct result, even though there is a perfectly adequate solution. Consider, for example, the following block:andlogical $B.b < “2 * [val $C.c]”logical $C.c < “[val $D.d] - 5”)Suppose that the block is processed in repair mode when B.b = 25, C.c = 10, and D.d = 10. Thefirst logical statement will be determined to have the value False, since 25 is not less than 2*10.The repair action might be the assignment B.b — 19. The second logical statement would thenbe processed and determined to have the value False, since 10 is not less than 5. The repairaction might be C.c <— 4. While that action would cause the second statement to have the valueCHAPTER 3 - Managing Configurations with the Prescription Language 43True, it would simultaneously cause the first statement to have the value False. The repair process would not detect this problem.In considering this example, note first that there is an obvious solution which would cause bothstatements to have the value True simultaneously (B.b — 7, C.c <— 4). Secondly, observe that inthis particular case, simply reversing the order of the statements in the block would make it possible for the repair algorithm to compute a correct solution.The problem which this example reveals is the inadequacy of the simple, naive repair algorithmwhen dealing with specifications involving certain dependencies. An obvious solution would beto use a more general solver, one capable of handling such dependencies and finding a solutionif one exists. There are a few reasons why effort was not expended in this direction:1. Awkward situations like that illustrated in the example do not seem likely toarise often in practice. The common situations in static system configuration are very simple.2. Inclusion of a more powerful solver would greatly increase the complexityof an implementation, and could make its operation more difficult foradministrators to understand.3. A simple repair algorithm has efficiency advantages. It is possible (at leastin theory) to write a specification equivalent in form to 3SAT, for whichfinding a solution is an NP-complete problem. Given the previous points,avoidance of an exponential algorithm is a good idea.3.8.4 Object LimitationsDirect modification of certain attributes of certain components is not possible. For example,consider the s ± z e attribute of a file, which we might define to be the size of the file in bytes.Now suppose that the following description is written:logical $F.size == 23CHAPTER 3- Managing Configurations with the Prescription Language 44If the size of file F is 23 bytes, all is well. If not, the repair algorithm will easily determine thatthe appropriate repair action is the assignment F.size <— 23. The problem is that performing thatrepair action is non-trivial. For this example, a simple algorithm can be devised, since there aresteps that can be taken to change the size of a file to any particular value. Unfortunately, it seemsunlikely that an automated algorithm will produce a desirable result in most cases.Repair will ultimately fail if it involves changing the value of attributes which are not directlymodifiable. The size attribute in the above example is a dependent attribute; its value dependson other properties of the object. Other attributes might be immutable, that is, not subject tomodification for some intrinsic reason. Using static analysis of specifications, an implementation could warn the user of possible problems with non-modifiable attributes.3.8.5 FailuresRepair can also fail for unpredictable reasons. A repair operation may simply not work when itis attempted. For example, an attempt to create a file will fail if the disk space is exhausted.Without a more elaborate reasoning system, the only solution to such a problem is to report it toa human.3.9 Repair Processing DetailsA few practical details concerning repair remain to be discussed. The target application for thelanguage is configuration of production systems. Administrators are only too aware of the problems that result when a system is inadvertently placed in an inconsistent state. Configurationmanagement tools must be carefully implemented to avoid contributing to the very problemsthey are designed to solve. They must also be designed to satisfy the need of administrators tounderstand exactly what is being done on their behalf.CHAPTER 3- Managing Configurations with the Prescription Language 45It is important that systems not be left in inconsistent states, as might occur if repair were to failpart way through processing a description. To avoid this situation, prescriptions should be handled atomically. Either a prescription should be True after processing, or the managed systemshould be in its original state. There are some problems with implementing atomicity asdescribed. These problems will receive more attention later in the thesis.The description of processing revolved around the two modes: verify and repair. In practice, verify mode is of limited utility, since it causes processing to terminate with the first encountereddiscrepancy. The difficulty with repair mode is that it involves modifications to the managedsystem which an administrator may need to specifically review and approve. The simple solution to these problems is to split repair processing into two phases. In the first phase, the repairactions to be performed are determined, during processing of the prescriptions. The actions arerecorded in a log. Execution is deferred to the second phase, after processing of statements iscompleted. The administrator can review the log between the two phases. Tools could even beprovided to permit manual editing of a log. Unlike the case with verify mode, the log caninclude a description of every way in which the managed system fails to match the specification.The two-phase repair processing approach will be referred to as deferred execution. Inaddition to the advantages described above, it helps achieve atomicity, since statement processing finishes completely before the first modification is made. Use of deferred execution causessome implementation difficulties, however. It requires maintenance of a large amount of stateinformation during the first phase, and special handling to avoid problems with dependencies onimplicit side-effects. These problems are explored later in the thesis. If an implementation wereto be used on an unattended basis, it might not be necessary to implement deferred execution,since atomicity can be maintained through a roll-back mechanism.CHAPTER 3- Managing Configurations with the Prescription Language 463.10 Standard Class InterfacesAs previously mentioned, class implementations serve to provide the translation between theuniform object abstraction used by the processing algorithms and the concrete syntax required toactually manipulate components. The processing code remains independent of the idiosyncracies of particular components (and, indeed, of particular operating systems).The processing algorithms function by invoking certain methods on objects. Any component ofa managed system can be handled as long as the class for that type of component supports themethods which are used by the processing algorithms. These methods are invoked during bothverification and repair processing.The standard interfaces may be organized into several groups by purpose. The following tabledescribes the methods in each group. Class methods are indicated by “(class)” following themethod name. Every class that is defined must support each of these methods. Default implementations are inherited from Object’.Table 3: Standard Object Methods by GroupGroup Method. DescriptionObject Management constructor Initialize objectAttributes getAttribute Get the value of an attribute.getDefault Get the default value of an attributefor a newly created component.setAttribute Set the value of an attribute.1. Collection methods are not required on non-container classes. The default implementations in Objectsimply raise an error.CHAPTER 3- Managing Configurations with the Prescription Language 47Table 3: Standard Object Methods by Group (Continued)Group Method. DescriptionClassification claim (class) Determine whether the object is aninstance of a specific class, when it isknown to be an instance of a generalclass.Testing isDeepEqual Test an object for equality withanother object using class-specificevaluation.Collection Related getCollection (class) Obtain the object which holds allinstances of a class, for classeswhose instances are all generallyheld in a single collection object.initlteration Begin iteration over objects in a collection.getNext Retrieve the next object in the iteration.endlteration Cleanup from iteration over objectsin a collection.find Locate an object by identifyingvalue.prepare Prepare a new object for addition to acollection.create Actually create a new object (andcomponent).destroy Destroy an existing object (and component).ismember Check for presence of an object in acollection.Modification commit Commit changes to object.Debugging printRef Produce human-readable version ofobject reference.As an example, assume that we are interested in managing disk files. We need to define a class,CHAPTER 3- Managing Configurations with the Prescription Language 48say File, to model disk files. In this situation, the actual files are the components. Every instanceof the File class is an object representing a specific disk file. We must provide implementationsof the standard methods to manipulate the real files. For example, when getAttribute is invokedon a File object for the s ± z e attribute, the implementation must perform the operating systemfunction to retrieve the size of the file represented by the object. For the Unix operating system,the implementation would use the stat system call. On another operating system, the implementation would use whatever function that system provides for obtaining the size of a file. The processing of a statement such as the following (with F referencing an instance of class File) wouldinclude an invocation of getAttribute.logical $F.size == 150Should repair be required for this statement, the setAttribute method would be invoked. For logfiles, we might define a LogFile class as a subclass of File. We could define the size attributefor class LogFile to be the number of lines in the file, then the setAttribute implementationcould truncate or expand a file as necessary to reach any specified size.Every attribute exposes some aspect of the configuration state of components modelled by theclass with which the attribute is associated. A class implementor can define attributes in whatever way seems appropriate, and provide implementations to get and set attribute values. Theprocessing algorithms operate using the standard methods, and incorporate no knowledge ofparticular components or operating systems.We could model directories by defining a Directory class1. Since directories contain files, theDirectory class would be a container class for objects of class File. The collection methodswould be implemented on class Directory to operate on files in the directory represented by aDirectory object. For instance, the find method would take a file name as an identifying value,1. For Unix, at least, Directory would be a subclass of File.CHAPTER 3- Managing Configurations with the Prescription Language 49and search the directory for a file with that name. Upon finding a file with the right name, themethod would create an object to represent that file, and return the object.The relationship of many of these standard methods to prescription processing is straightforward. There are a few methods whose purpose is not clearly explained by the above table, however. Some of these will be dealt with in the next section, but the rest can be explainedimmediately.The claim method is required to deal with class inheritance hierarchies that model classificationhierarchies. The prime example of this is Unix files. In Unix, a directory can be viewed as a typeof file, as can a symbolic link, a device special file, and so forth. We can model this by defininga root class File, with child classes Directory, SymLink, etc. A Directory would then be formallydefined to contain objects of class File. Suppose that we then want to write a prescription statement such as the following:forall S SymLink $dir U {logical $S.mode == 0755}When the statement is processed, objects are extracted from dir, but those objects may bedeclared to be of class File or Directory in addition to SymLink. The claim interface is used todetermine whether the object is actually of the required SymLink class.The isDeepEqual method is required to deal with object comparisons that cannot be made without knowledge of the particulars of the component. It is used to implement the eq operator ofthe logical statement.The getCollection method is particularly unusual. It is used to translate foreign keys in the fieldsof specification tables into the objects they reference. This method is unlikely to be needed formodelling managed components.CHAPTER 3- Managing Configurations with the Prescription Language 503.10.1 Implementing Deferred ExecutionSupporting the deferred execution strategy, which was introduced in Section 3.9, is a significantissue for the class implementor. There are two processing phases, and all modifications to managed components are deferred until the second phase. This causes a problem of tracking managed system state.Deferring operations requires that the software keep track of the intended state of componentsthat are slated for modification. To understand why this is so, consider the following statement:require F File /tmp/example $root {logical $F.perms == 0755Suppose that when the above statement is processed, the software determines that file / tmp /example does not exist and must be created. Using deferred execution, the creation will belogged, but not performed immediately. Processing will continue with the block in therequire. Now the system must process the logical correctly, despite the fact that it refersto a file which does not exist (yet).The problem here is the same one that occurs when one attempts to build a virtual file systemthat can diverge temporarily from the underlying stable storage. The solution is the same aswell: the software must maintain enough information to process requests from memory, withoutreferencing the underlying system directly.In the context of implementing the Prescription language, there are two ways to organize themaintenance of state representation:1. Object state can be maintained entirely by class implementations usingobject instance data.2. Object state changes can be recorded centrally by the main processing code,CHAPTER 3- Managing Configurations with the Prescription Language 51without involvement of the class implementations.The second of these alternatives is attractive from the point of view of simplifying the classimplementor’s task, and reducing functional duplication between class implementations. Forthese reasons, the second alternative is supported in the prototype implementation.The processing algorithms do not invoke methods directly. Instead, they call special procedureswhich may or may not invoke the appropriate method on an object, depending on the recordedstate of the object. Only a few pieces of state information are maintained. There is a generalstate indicator, which records whether the component is pre-existing, slated for creation, slatedfor destruction, or slated for modification. Lists of objects to be added or deleted are maintained,to track changes to the membership of collections. Finally, the new value of any modifiedattribute is recorded.By relying upon central record keeping, a class implementor does not need to worry about thepossibility that an attribute value will have been slated to change. The class implementation canjust access the modelled component to respond to every getAttribute request. If the attributevalue does need to change, the new value will be centrally recorded, and subsequent requests forthe value of the attribute will be satisfied without invocation of getAttribute on the object at all.It turns out that there are a couple of situations in which this strategy fails. These account fortwo of the surprising methods in the standard set. First, when an object is created (through processing of a require statement), it is not possible for the central record to satisfy requests forthe value of attributes, but it is also not appropriate to invoke getAttribute, because the managed component does not yet exist. The getDefault method is invoked instead of getAttributein this case to retrieve the value that the attribute should have when creation actually completes.The second situation concerns creation itself. It is important that the class implementation for aCHAPTER 3- Managing Configurations with the Prescription Language 52collection perform the creation of any object to be added to the collection. The prepare methodhandles this part of creation.The complete mechanism described above works well for some classes, but it does not solveevery problem. One issue that remains is the handling of components that cannot be individuallyaddressed in the managed system. For instance, entries in a simple Unix configuration file canbe modelled by objects. The various fields in an entry can be treated as attributes. A problemarises in the second phase of repair, when changes are actually being made. The problem occurswhen it is not possible to independently modify the field of one entry without affecting surrounding fields or records. In order to implement setAttribute under the scheme describedabove, it would be necessary to read the entire file and write it out again, changing the value ofone field in the process. Now imagine what happens when a number of modifications are madeto different records in the same file. The implementation just described would result in the filebeing read and written several times. With components like records in a file, which cannot beindependently modified, the best implementation strategy is to make all modifications to a representation in memory, then simply regenerate the file after all the changes have been recorded.This approach requires the class implementation to track state changes.Fortunately, the class implementation can do whatever is appropriate with the instance data, sothere is no fundamental conflict with the mechanisms described previously. There is a need for amethod to be called after all modifications from the log have been completed. The standardcommit method is the one designated to fill that role. A list of every modified object is maintained. After processing of the log is finished, the commit method is invoked on each object inthe list. A interface is supported to permit the implementation of a class to add an object to thelist of modified objects. This is used, for example, so that the implementation of a class modelling records in a file can add the object modelling the file itself to the change list.CHAPTER 3 - Managing Configurations with the Prescription Language 53In summary, there are two implementation strategies available to the class implementor. Following the first strategy, the methods all reference the modelled component directly (except forthose like getDefault), and state tracking is ignored. Following the second strategy, the classimplementation maintains a complete model of the component state, and only references thecomponent directly at construction time and during commit.The mechanisms introduced here still do not address every problem. Attributes with inter-dependencies cannot be properly supported. For example, if a change to the value of oneattribute implies a change to the value of another attribute, the situation cannot be modelled withthe available mechanisms. A central record will be made of a modification to one attribute without any invocation on the object. To deal with inter-dependencies, more standard methodswould be needed.3.11 ExampleThe example presented here is intended to illustrate how all the elements described in this chapter fit together. A simple, hypothetical situation is used in order to limit the length and complexity of the example.Consider the management of an electronic mail system. In this system, assume that there is afolder for each user. Folders may be created in a structure called a file cabinet. This managedsystem is modelled by the following classes:class Message Object {} {attribute from String immutableattribute date Dateattribute text String}class Folder Object Message tattribute name String immutableattribute group Stringattribute size IntegerCHAPTER 3- Managing Configurations with the Prescription Language 54}class FileCabinet Object Folder {attribute name String immutable}class System Object FileCabinet 0From these definitions, we note that the configuration state of a folder consists of a name, agroup, and a size (the number of messages which the folder can contain), plus the set of contained messages. The configuration state of a file cabinet consists of a name and a set of contained folders. The method definitions are omitted here, because they are essentiallyimplementation details.For this managed system, assume the administrators wish to specify the details of the foldersneeded by students enrolled in various courses. All student folders will have the same size, andthe administrators naturally want to avoid entering that value many times. The following table isadequate to hold the varying instance data:table StudentFolder students.table { \{name String) \{course String) \} {name) {}Note that there are two fields in every record. The name field holds the student’s name, andserves as the primary key. The course field holds the designation for the course in which the student is enrolled (assuming that students are only enrolled in one course at a time, for this example). Here are some sample records:Table 4: StudentFoldersname courseJohn Tan CPSC 124Mary Alder CPSC 128Lucy Denter CPSC 126CHAPTER 3- Managing Configurations with the Prescription Language 55Table 4: StudentFoldersname courseTom Roe CPSC3 19J0 Terry CPSC415Now a prescription is required to describe the configurations of objects in the managed systembased on the data in the table. The following simple prescription is adequate in this case:prescription StudentFolders {T} {require FC FileCabinet Students $System {forall E StudentFolder $T {) {require F Folder $ $FC {logical $ s= $E.courselogical $F.size == 100}}}}The prescription describes the existence of a file cabinet with the name “Students” containingone folder for each record in the StudentFolder table. The name which identifies each folder isthe name from the record in the table. The group for each folder is the course designation fromthe table record. Finally, the size of each folder is specified to be 100. The table must be suppliedas the parameter T when the prescription is activated. The variable System is assumed to bebound globally to an object representing the entire managed system.This simple example demonstrates how a managed system can be defined by a set of class definitions, how a table can be defined to contain the varying details of a specification, and how aprescription can be written to complete the specification and express the details which do notvary. The prescription above can be activated in repair mode to automatically configure themanaged system, or to obtain a complete report of the ways in which the managed system deviates from the specification.56CHAPTER 4 ImplementationImplementation of the Prescription language poses a number of challenges. This chapterdescribes the details of the prototype, and presents the issues which are significant for anyimplementation.The prototype described here was produced in order to explore implementation issues, and permit the experiment presented in the next chapter to be conducted. The implementation wasnever intended to be suitable for production use. It is “one to throw away.”4.1 The EnvironmentUnix is a natural choice for the prototype operating system environment. The examples considered during the development of the model and language were Unix related, and Unix is the primary computing environment in the Computer Science department at the University of BritishCHAPTER 4- Implementation 57Columbia. Despite the focus on Unix, both the language and the central ideas of the implementation are transferrable to other contexts.For convenience, the prototype implementation was produced for SunOS 4 systems only. Mostof the code should work on other systems unmodified. The sample class implementations, however, are quite specific to the operating system variant.The prototype implementation is written exclusively in the interpreted language Tel [1], andrelies on the standard interpreter. There are a few reasons why Tcl is appropriate for this project.1. Tel provides facilities which permit extension of the interpreter to supportnew language features, including new control structures. It is important torealize that this involves more than a facility for defining new commands orprocedures. Syntactically, the extensions appear as though they were part ofthe base language, which is particularly convenient.2. Tcl has the basic features that are desirable for a prototyping activity. It is avery high-level language, supporting simple manipulation of strings andlists. It is interpreted, and it supports automatic storage management.3. Through common extensions, Tel has support for direct interaction withUnix and high-level RPC for writing distributed applications.Since the Tel interpreter plays a significant role in the implementation, the syntax has to conform to that accepted by the interpreter. Thus, it is actually Tel syntax which has been used up tothis point1.The Tel syntax is acceptable, if less than desirable. The more serious disadvantagesto the use of Tcl have to do with efficiency and the lack of typing. These problems will beexplained later. Despite its limitations, Tel serves the purpose admirably.1. The origin of the syntax was not explained in the previous chapter to avoid confusion between the Prescription language and Tcl.CHAPTER 4- Implementation 584.2 Basic ProcessingThe implementation relies on the Tcl interpreter, as already noted. A Tcl procedure is defined inthe interpreter to implement each statement in the Prescription language. The prescriptions areactually executed by the Tcl interpreter.The basic procedures that are defined to implement the descriptive statements of the languageare and, or, prescription, narrow, logical, torah, disallow, and require. Inaddition to these, an activate procedure is defined to initiate processing, various support procedures (documented earlier) are defined, and the definitional procedures related to class andtable definition are provided. A large number of other procedures are part of the implementationinternals.The blocks that are part of most descriptive statements are merely string arguments to procedures, as far as the Tcl interpreter is concerned (recall that braces are string delimiters). This isexactly how the basic control structures of the Tcl language itself are implemented. Bracesinhibit substitutions. Thus when a statement such as:frodoputs “Hi there $mom”}is executed, the interpreter passes the contents of the braces as an argument to frodo, withoutperforming a substitution of the value of variable mom. The implementation of frodo caninvoke the interpreter on the argument, in the variable scope in which the call to frodo wasmade. At that point, the interpreter will perform the variable substitution.In order to implement the Prescription statements in an interpreter, unusual transfer of the flowof control must be possible. Tcl provides the ability to throw and catch exceptions, which makesimplementation of new control structures possible. The prescription implementation uses threeCHAPTER 4- Implementation 59special exceptions: one that means a statement had the value False, one that means a statementhad the value True, and one that signals the end of an iteration.Various pieces of processing state are stored in global variables. Of these, the most important isthe PSmode variable, which holds the indication of which processing mode is active at anypoint in time. Also significant is the PSblock variable, which holds an indication of whichblock type (Or or And) is active. This information is needed in order to determine what actionshould be taken in various cases.Each procedure that implements a descriptive statement finishes by returning the result of invoking a common procedure called value. The value procedure is invoked with an indication ofthe value that has been determined for the statement. There are three possibilities: True, False,and Error. The third case is used when an error is encountered. The value procedure takes oneof three actions based on the value indication it receives, and the current processing state:1. If Error was indicated, a normal error exception is raised. Such an exceptionwill propagate all the way to the top level.2. In some cases, value simply returns, causing processing to continue withthe next Prescription statement.3. In other cases, value raises one of the special exceptions to alter the flowof control. The special exceptions are caught and handled further up the calltree.In the context of an And block, statements must be processed sequentially until either all havebeen processed, or one has the value False. Thus value will simply return on True in an Andcontext, and throw the False exception on False. In an Or block, processing continues sequentially until a statement has the value False, so the return action is different. Simple return occurson False (to cause execution to proceed), and the True exception is raised on True.CHAPTER 4- Implementation 60The remainder of this section is devoted to brief summaries of how the individual blocks andstatements work.4.2.1 andThe and procedure is very simple. It saves the old PSblock setting, sets PSblock to And,and then invokes the interpreter on the block. Any exceptions are caught, so control is guaranteed to return to and on termination of block execution. The saved PSblock value is thenrestored, and value is called to end. When no exception is raised, all statements in the blockmust have the value True, so the statement has the value True. Exceptions are simply re-raised.4.2.2 orThe or procedure is a bit more complicated then and, due to problems of repair. Basically, theblock is processed first in verify mode, regardless of the operative mode. This is necessary sothat procedures in the block do not attempt repair before the need for it has been established. Ifthe block execution terminates without an exception, all statements must have the value False,so repair is required if the original mode was repair mode. The mode is reset, and if repair isrequired, the block is executed again in repair mode. This will cause each procedure to attemptrepair. In the context of an Or block, a True value for a statement will cause an exception to beraised. That exception has the effect of terminating block execution.4.2.3 prescriptionThe prescription procedure implements prescription definition. Both definition and activation will be described here. When a prescription is defined, a new Tcl procedure is created withthe same name as the prescription. The argument list of the new procedure is just the parameterlist of the prescription. The body of the new procedure consists of a call to a special pre-processprocedure, a call to and with the prescription body, and a call to a special post-process proceCHAPTER 4- Implementation 61dure. When a prescription is defined as narrowed (with the -narrow switch) the call to and inthe body is enclosed in a call to narrow. Since a new procedure is defined, activation of theprescription may be written simply as a normal Tcl command, as has been illustrated previously.The special procedures called in the body perform mostly administrative and data managementoperations. They do not normally alter the flow of control. Note that exceptions generated during execution of a prescription body propagate to the block that contained the prescription activation.4.2.4 narrowThe narrow procedure is very simple. It merely saves the current mode indication, sets themode to verify, and executes and with the block. Any exceptions are caught so that the modecan be reset, but exceptions are merely propagated upwards. Thus the narrow procedure doesnot directly affect the flow of control.4.2.5 logicalThe logical procedure is straightforward, although there are a couple of independent cases. Ifthe attribute/operator pair are omitted (by passing empty strings), the expression part is simplypassed to the Tcl expression evaluator. The result determines the value of the statement. In theprototype implementation, processing of non-repairable logical statements in repair mode generates an error. When all parts of the statement are supplied, the procedure still passes theexpression to the Tcl evaluator, but then obtains the value of the referenced attribute, and cornpares that value to the value returned by the evaluator. If the result is False then a repair procedure is invoked to set the attribute in question to an appropriate value.CHAPTER 4- Implementation 624.2.6 forallThe basic strategy for both forall and disallow statements involves iterating through themembers of the specified collection. For some require statements, iteration is also necessary.A common internal procedure handles all three iteration situations. Iteration involves the samebasic steps regardless of which type of statement is being processed. Objects are extracted fromthe collection one at a time. Each object is bound, in turn, to the given variable name, using a Tclcommand. Each object is evaluated to determine whether it meets two constraints:1. The type constraint given by the type specification for the variable.2. The supplied constraint expression (applies only to forall and disallow)For each object which meets the constraints, the block is executed. The actions taken, based onthe results of executing the block, vary depending on the type of statement. In the case offoral 1, a False exception for the block implies a False value for the statement. Otherwise,iteration continues until there are no more objects, at which point the statement must have thevalue True. To handle statements over the closure of collections, each object is checked to determine whether it is a collection containing the same type of objects as the original. Such collection objects are added to a queue of collections from which objects are retrieved. Iteration endsonly when the queue is empty.The forall procedure does not implement any special repair actions, because repair mustalways be performed by procedures contained in the block.4.2.7 disallowThe disallow procedure calls the iteration procedure whose basic operation is describedabove. For disallow, the only special action occurs when an object is found for which theCHAPTER 4- Implementation 63body has the value True. In repair mode, an attempt is made to destroy the offending object, andcontinue with the iteration. In verify mode, iteration stops immediately because the statement isknown to have the value False. For a disallow block, execution always proceeds in verifymode, to prevent statements contained in the block from attempting repair operations.4.2.8 requireThere are two cases for require to handle. When no identification value is provided, the statement is implicitly narrowed, and processed by iteration using the common iteration proceduredescribed above. Iteration terminates for require as soon as an object is found for which thebody has the value True. If no such object is found, the statement has the value False.When an identification value is provided, an entirely different algorithm is used, one that doesnot involve iteration over the contents of the collection. Instead of iterating, the identificationvalue is used to search the collection for a candidate object. If none is found and repair mode isactive, repair is initiated with the creation of a new object having the required identity. When anobject is available (either because it was found in the first place, or because it was createdthrough a repair operation) it is bound to the variable, and the block is executed. The value ofthe block then determines the value of the statement.4.3 Objects and DataThe base Tcl language uses strings as (almost) the only data type. The Prescription languagerequires support for more sophisticated data structures. It was necessary to have Tcl variableshold references to objects, and then to be able to deal with attribute references involving variables as was illustrated earlier. Sometimes variables also need to hold simple string or numericvalues, which Tcl can intrinsically manage.CHAPTER 4- Implementation 64One way to deal with references and data is to use variables exclusively to hold object references. Objects could be created for each simple value, and the values handled through references to objects. While this approach has the benefit of consistency, it causes a lot ofinconvenience when simple values are used.An alternative approach is used in the prototype. Variables may hold both ordinary Tcl valuesand object references, and a special structure is used to distinguish object references. Object references begin and end with a special character sequence that is deemed to be uncommon in ordinary values1.Attribute values are used throughout prescriptions. Consider what happens with a reference suchas the following.$obj . one, two. threeThe Tcl interpreter is capable of performing value substitution for the Tcl variable reference($ obj in this case). The interpreter leaves the remainder of the string alone. In order to useattribute values, it is necessary to invoke a procedure which can interpret the string left aftersubstitution by the Tcl interpreter. The procedure is called va 1. What va 1 does is take a stringconsisting of an object reference (distinguished by the special prefix and postfix string) followedby a period-separated list of attribute names. It dereferences the string by performing getAt —tribute operations, and returns the final value. For convenience, val will return an ordinarystring unchanged. The typical use involves the in-line procedure invocation mechanism of Tcl,and is written as follows:[val $,two.three]1. The sequence presently consists of the ASCII vertical tab character, but could be easily changed.CHAPTER 4-Implementation 65Many procedures that are part of the implementation expect to receive object or attribute references as arguments, and deal with them appropriately. It is only necessary to use val explicitlyin situations where an ordinary value must be supplied (e.g. in a Tcl expression).The format of object references, storage of instance data, and invocation mechanisms are alldescribed in the next section.4.3.1 Object System ImplementationThe base Tcl language provides no direct support for object-oriented programming. Althoughthere are extensions which add object-oriented support, a small, custom object system is used inthe prototype implementation. A custom solution has the benefit of supporting the featureswhich are needed for this application.A single inheritance class structure is supported, as described earlier. Per-class instance data isallocated transparently to the class implementations. Remote invocation is supported. Thesebasic features are all common in object-oriented languages.One unusual problem in this application is the problem of object recognition. The purpose of thesoftware abstractions called objects is to represent components of managed systems, such asfiles, directories, or processes. The objects, however, are only created as needed. For instance, ifa prescription describes a particular file (with a require statement), an object will be createdto represent that file, although objects may not exist to represent other files in the same directory.During processing of a prescription, however, the same component may be described multipletimes (e.g. by require and also by Eorall). The system must recognize any component forwhich an object has already been created, so that on subsequent reference the existing object isused (with the proper model state) and a new object is not created. By object recognition, thesystem avoids having multiple mutually inconsistent models for a single managed component.CHAPTER 4- Implementation 66In order to efficiently solve the recognition problem, objects are referenced by global identifiers(GIDs) which are derived from the identification information of modelled components. When acomponent is referenced, the software can simply generate the GID, then check to see whetheran object already exists for that component. This approach to object references differs from regular practice in object-oriented languages.In the prototype implementation, an object reference is composed of three parts:1. Identifier of the class of which the object is an instance.2. Identifier of the machine on which the object resides.3. GID for the object.These three items, along with the class definitions, provide enough information to invoke amethod. It may seem obvious that the class identifier should somehow be stored with theinstance data, and not passed around in references. That would introduce a small problem for theclaim method, which modifies the reference to an object when claiming it. The machine identification could probably be handled differently as well. In the prototype, the three parts of a reference are combined in a Tcl list (which is just a string with a particular format). The generation ofGIDs from components must be performed by the class implementations.Instance data are stored in a single array on each machine. The array is a Tcl associative array1,indexed by a combination of GID and class. This arrangement provides, for each object, onearray slot for each class in the object inheritance hierarchy. The slot may contain any string, andso may be structured as a list to hold multiple items. A specific slot is not arranged for eachdeclared attribute, as might be expected. This is because the attributes apply to the modelledcomponent. There is no reason that the mapping between stored instance data and supported1. The associative array of strings is the only data representation supported in Tcl, apart from strings themselves. Access to individual slots is implemented efficiently.CHAPTER 4- Implementation 67attributes must be 1:1. Instead, a class implementor is free to organize the instance data in whatever way seems most appropriate. For each object, one instance data slot is reserved for use bythe prescription processing code (the slot associated with Object, the minimal root class). Thereserved slot is used for the central records maintained to deal with deferred execution, asexplained in Section 3.10.1.Classes are defined by the use of procedures class, method, class_method, andattribute. In the prototype implementation, the explicit declaration of attributes is entirelyat the discretion of the class implementor. If attributes are explicitly declared, then the processing code will use the declarations to check references, otherwise the class implementation mustassume more verification responsibility. Since Tel has all the facilities required of a class implementation language, method code can be included directly in the method definition, as illustrated by this example.class FriendlyClass Object {} {attribute greeting String {}method greet {name} {return “Hello there $name”class_method identify {} {return “This is the Friendly class!”}The explicit declaration of the class of contained objects is another unusual feature of this objectimplementation. The prescription processing code uses the contained object information to process statements that relate to collections (forall, require, disallow).The method invocation mechanism is a straightforward implementation of dynamic methodlookup. When a method is invoked, hidden parameters self and gid are passed in, to provideinstance information. The invocation code also arranges for local variable idata to be boundto the appropriate instance data array slot (using a Tel feature). A procedure called super isCHAPTER 4- Implementation 68provided to permit the implementation of a method to invoke the superclass implementation ofthe same method. The invocation mechanism for class methods is very simple, as there are noclass objects. No inheritance-based search is performed to find a class method; it must bedefined on the specified class or an error is raised.4.3.2 Deferred ExecutionThe subject of deferred execution has already been addressed in considerable detail. The centralrecord keeping code consists of a set of Tcl procedures with the same names as the methods inthe standard set. These procedures are collectively known as the Object layer of the implementation.4.4 Prototype ClassesIn order to handle the desired examples, a number of classes were written as part of the prototype implementation. This section presents the interesting details of the prototype classes. Notethat these class implementations are very specific to SunOS 4.CHAPTER 4- Implementation 694.4.1 FilesClasses were written to model Unix files, directories, and symbolic links. The inheritance hierarchy for the classes involved is shown in Figure 1. The primary class is the File class, whichmodels all Unix files. A number of attributes such as name, fuilPath, size, and group are supported.All file objects use the same GID format: /File/hostnamelpathname. Since Unix files may havedifferent names (due to links in the filesystem), this is not an adequate GID format for a production system. It is convenient for prototyping, since the file path can be extracted.The only methods which are actually implemented in class File are printRef, getAttribute, getDefault, and setAttribute. For all other standard methods, either the default implementations inclass Object are adequate (regular methods) or the method will never be invoked (class methods).Figure 1 — File Class HierarchyCHAPTER 4- Implementation 70The FileContents class exists for the contents attribute of File objects. The primary methodimplemented in class FileContents is isDeepEqual. Through this method, the contentsattribute may be used to describe one file as a copy of another.The Directory class is quite substantial, since a Directory object is a collection of File objects.The claim class method and the various collection related methods are implemented in classDirectory. One of the trickiest issues in the Directory implementation concerns the attribution ofnew objects extracted through the getNext method. Normally, such objects are created asinstances of File, but directories are immediately declared to be of class Directory. This is necessary in order for the code that handles closures to work correctly. Key values for requirestatements (used in invocations of find) are simply file names, so lookup is quite efficient. Inaddition, the implementation of iteration supports optimization for a very particular form of constraint expression involving the globEQ function. This optimization is extremely primitive, tothe point of being slightly incorrect, in a way that will be described in the section on limitations.The SymLink class models symbolic links. The nature of symbolic links in Unix poses particular modelling difficulties. In most cases, a symbolic link object needs to be treated as the entityreferenced by the link, not as the link itself. On the other hand, a symbolic link has an attributewhich other files do not have, namely the item to which the link points. Due to this classificationproblem, the claim method is particularly important for SymLink objects. An object that modelsa symbolic link will only be declared to be of class SymLink if it is referenced in a statementwhich uses the SymLink type explicitly. The default value of the ref attribute of a SymLinkobject is always “/dev/null”. In the prototype implementation, a SymLink is actually createdpointing at the null device initially. In practice, creation should always be followed by a setAttribute invocation which sets the link to point somewhere in particular. Setting the refCHAPTER 4- Implementation 71attribute involves destroying the link. Thus some efficiency could be gained by tracking the statein memory and only adjusting the managed system when commit is invoked.4.4.2 Fstab and Printcap ClassesTwo Unix configuration databases, /etc/fstab and /etc/printcap are modelled by prototypeclasses. For each, there is a main class (e.g. FSTAB) that inherits from File, and a record class(e.g. FileSysRecord) that inherits from Object. The implementation of these four classes followsthe strategy of directly tracking the component states. The constructors for the collection objectsread the file data and store it in memory. Changes are made to the in-memory copy, and theentire file is rewritten on commit (which is only invoked if modifications were made).Since the collection classes are subclasses of File (in recognition that the databases are stored infiles), the GIDs follow the format for File GIDs. The GIDs for records are composed from thehostname of the file, the path of the file, and a key value for the record.The key values are appropriate to the databases in question. For class FSTAB, an identifyingvalue must be an ordered pair (servername, filesystemname). For the Printcap class, an identifying value must be the name of a printer entry. Neither class supports any optimizations for iteration.4.4.3 Table ClassesClasses for specification tables are an important part of the implementation. Inheritance is usedeffectively with tables. There is a Table class and a TableEntry class. Both of these contain complete generic implementations. The class created for each specific table, and the class created forentries of each specific table, are empty subclasses of the two generic classes.CHAPTER 4- Implementation 72As noted earlier, the prototype implementation of tables relies on text files with a simple structure. The data for the table is read from the file specified by the filename parameter to thetable definition statement. The expected format is a sequence of records delimited by new-lines, each containing the same number of fields delimited by the field-delimiter string.Fields in a table all have declared types. When a value is requested for a field of a fundamentaltype (using getAttribute) the value is returned exactly as it is written in the file. Alternatively, afield type may be the name of another table or class, or a list containing values of some otherspecified (non-list) type. If the field type involves a class, the getAttribute code treats the valuerecorded in the file as a foreign key identifying an object in the master collection for the specified class. The master collection object is retrieved by invoking the class method getCollection.When the field value is requested, the referenced object is obtained and returned. This mechanism is used primarily in the case of fields which contain foreign keys for records in other tables.When the special @ syntax is used, reference translation is suppressed and the literal value isreturned.The table implementation does not support any form of modification to tables through repairprocessing, because the tables are considered part of the specification, not part of the managedsystem. Prescriptions may be written to discover errors in tables, but automated repair will notwork. It is perfectly reasonable to develop classes for tables as a components of a managed system, as the Printcap and Fstab classes demonstrate.4.4.4 Machine ClassMachines are also modelled by a class. A table is required to define the known machines to thesystem. The attributes of a machine are the attributes of the entry for the machine in the definition table, plus attributes whose values are particular objects on the machine. For instance, theCHAPTER 4- Implementation 73root attribute is the object which models the root directory of the machine. The primary purpose of the Machine class is to provide access to objects on a machine. The handling ofmachines is explained in more detail in the next section.4.5 Distribution FacilitiesThe configuration management problem addressed by this thesis is fundamentally a distributedproblem. The prototype implementation has a basic set of mechanisms for dealing with distributed systems. As language validation was the primary objective, the distribution scheme is relatively weak.One central machine must be designated as the master. It is this machine which must have accessible copies of all the Tcl code, as well as direct access to the database files and configurationdescriptions. All other machines (called slaves) require only TCP/IP reachability’ from the master, and an appropriate Tcl interpreter. No shared filesystems are assumed between machines,and if available they are unused.Interaction between machines is supported by the DP extension [2] to the Tcl interpreter. Thisextension provides a powerful RPC mechanism by which Tcl commands may be executed onremote machines and the results returned. Both master and slave machines act as RPC servers.On slave machines, starting the server is the only local initialization step that must be performed. All necessary code is downloaded into the interpreter automatically by the master whenthe slave is first accessed. Thus the part of the configuration management system that runs onevery machine as small and generic.In order to support distribution, a database table must be provided to define machines. The tablemay include any attributes desired, but must have name and aliases attributes. A procedure1. Reachability is assumed to be reflexive.CHAPTER 4- Implementation 74called machine is invoked to create Machine objects based on the contents of the table. Initially the objects that model machines are all declared to be of class MachineProxy (a subclassof Machine).Access to machines represented by MachineProxy objects is avoided by means of a hack.Whenever a prescription is activated with a parameter that is a MachineProxy object, the activation is elided, and the prescription is summarily declared to have the value True. This simpletechnique permits processing to proceed even when some known machines are inaccessible. Thetechnique seems to work remarkably well in practice, but would distort the logical evaluation ofsome prescriptions unacceptably.The procedures engage and disengage are provided toenable and disable access to machines respectively.A Machine object is always created on the machine which it represents. The master simplykeeps references to the Machine objects on hosts around the network. A special class with onlyone instance (AllKnownMachines) is provided as a collection.The processing of prescriptions is fundamentally centralized in the prototype implementation. Infact, all statement processing actually occurs on the master machine, with the slaves accessedonly to perform operations on objects which are not on the master machine. Objects whichmodel managed components (as opposed to representing database contents) always reside on themachine which contains the modelled component.The prototype implementation follows a strict push model for managing a network of machines.This helps achieve synchronism, since whenever a change is made to the master configurationdatabase, all machines can be immediately updated. When a pull model is used, it is more difficult to arrange for machines to be updated in a timely fashion after a configuration change. Onthe other hand, there are situations in which a pull model is more appropriate, as in the case of aCHAPTER 4-Implementation 75machine returning to normal operation after having been turned off for an extended period.Using the prototype implementation, a machine could send a request for engagement to the master, then cause the master to process prescriptions again, but that would affect all activemachines and involve a lot of redundant work.The push approach described here could easily be adapted to eliminate redundancy. The masterwould need to keep track of the state of various machines, with respect to prescriptions that havebeen activated. When a slave contacts the master after having been down for awhile, the mastercould respond by performing the prescription processing required for that slave.In the context of a distributed system, a number of standard problems arise. For instance, there isthe problem of a single point of failure at the master. There is also the problem of network partitioning. These issues have not been addressed in this work.Ideally, a production system would be much more distributed in nature than the prototype implementation. The central base of prescriptions and database descriptions should be automaticallyfactored to produce smaller descriptions of the configuration of each individual machine. Theprescriptions for each slave could then be transferred to it and processed locally as required. Acentral processing capability could easily be preserved for those machines which are not suitedto local processing for some reason (e.g. X-terminals). Updates for most machines in this casewould consist of prescription updates, and the master machine would primarily play the role of aspecialized database server. In such a scenario, it is conceivable that the complete description ofa machine configuration would be a combination of descriptions of different types, with someparts specified locally, others controlled centrally.CHAPTER 4- Implementation 764.6 Administrative SupportA couple of administrative mechanisms support the rest of the implementation. The loggingmechanism has already been mentioned. A simple trace mechanism is also included; it permitshelpful messages to be produced when something goes wrong.During the first processing phase a log is maintained of the repair operations that are to be performed in the second phase. The log is stored as a Tcl list. Each entry consists of a type field, anidentification of the code that generated the entry, a reference to the object which the entry isabout, and data describing the operation. The start and end of processing of each prescription isrecorded in the log in order to identify the context of recorded operations when the log isreviewed by a human. The prototype implementation contains a minimal facility for printing thelog, along with code to perform the operations recorded in the log. One shortcoming of the logging mechanism is that a log entry about an object modification is recorded on the machine onwhich the object resides. There is no adequate central mechanism for accessing and manipulating these logs which are spread across various machines.The tracing facility is provided in order to gather enough information to create informative messages for an administrator when something goes wrong. When an error occurs (or a prescriptionis determined to have the value False) it is useful to know what statement was being processed.The tracing mechanism is called in various places to accumulate a prescription activation trace(the equivalent of a procedure call stack trace). The stack trace maintained by the Tcl interpreteris not useful, because it contains too many frames of implementation procedures. The prototypetrace facility is very limited, but is helpful nonetheless.CHAPTER 4-Implementation 774.7 Issues, Limitations, and ProblemsThis section is devoted to descriptions of a range of discoveries from the implementation exercise. Some of the issues and limitations have already been mentioned, but are explained in moredetail here. Many of the topics in this section are general, and not solely applicable to the prototype implementation. Note that performance issues are not mentioned here, since they are covered in a separate section which follows.4.7.1 Inter-class DependenciesIn the prototype set of classes, there are frequently strong dependencies between the implementations of different classes. Some of this is natural and seems unavoidable. For instance, allclasses that model files share a common GID format. Other dependencies may reveal architectural problems. For instance, the create method of the Directory class performs creation operations for instances of the classes File and SymLink as well as Directory. The general problemmay be the fact that no class methods are invoked to accomplish creation. Methods are onlyinvoked on the collection object which will contain the new object.4.7.2 Multiple Architecture SupportThe prototype implementation and trial example do not adequately explore the problems of supporting multiple architectures. There are two ways in which the language and model should bewell suited to multiple architecture support. In the first place, prescriptions can be easily conditionalized based on architecture, using the ± f statement. Furthermore, there is a good possibilitythat minor distinctions between similar systems can be hidden behind the object abstraction. Forinstance, two variants of Unix might have slightly different forms for the printer definition database, but the differences might be at a syntactic level. If so, they can be handled entirely by different class implementations. I expect that separate class implementations will be required forCHAPTER 4-Implementation 78each system, even though there may be a common abstraction that all the implementations support.4.7.3 GID ProblemsThe object recognition problem creates the need to use global object identifiers that are unique,and that can be generated correctly by looking only at a managed component. The GID formused in some of the prototype classes is inadequate for a production environment. Recall that theFile class (and descendents) use GIDs based on file name. The problem with that choice hasalready been mentioned. A more appropriate GID structure for Unix would be based on the(host, device, mode) triple. The problem with such a GID form is that mapping from the identifying triple, to a name that can be used in operations on the specific item, is non-trivial. Thesolution is to maintain the path information in the object instance data, but that introduces theproblem of multiple paths to the same item. The problems related to links and GIDs are discussed in the next section.4.7.4 Component ClassificationThe basic problem of component classification arises with symbolic links, as has already beendescribed, and also arises with hard links and possibly other structures. The managed system hasthese subtle features which create possible ambiguities. How are we to model such things? Theprototype solution is not entirely satisfactory. With a better GID scheme, as discussed above, abetter scheme for handling files referenced by symbolic links could be introduced. When referenced as a file or directory, a symbolic link should probably be bypassed, and an object generated to model the referenced item. Then there is a problem with classifying an object as to thecollection in which it resides. If an object needs to be recognized as being contained in everydirectory from which it can be accessed, every link must be found; such a search is a non-trivialexercise.CHAPTER 4- Implementation 794.7.5 Implicit Side-effects and DependenciesImplicit side effects cause problems. Inter-attribute dependencies cannot be handled using thestandard method set, as explained in Section 3.10.1. Another form of implicit side effect occurswith the description of entries existing in an fstab database. The purpose of such an entry is todefine a filesystem, and often all defined filesystems are mounted when possible. We canassume, therefore, that modifications to an fstab file are intended to imply changes to the set ofmounted filesystems. If the implication is correct, then the implementation of the commitmethod in the appropriate class should perform mount/unmount operations. Here we encounteranother problem with deferred execution. The problem is that the implicit side effect of creatingan entry in the table may be depended upon by prescription statements processed after the statement that describes the entry. The Object layer attempts to provide a generic solution to thedeferred execution problem, but it cannot generically handle implicit side-effects like themounting of a filesystem. With this particular case, we can observe that mounting a filesystem isan operation that may be easy to reverse. Thus the implementation could be changed so that theprepare method on the FSTAB object actually goes ahead and performs the mount operation.That fixes the problem of the dependency on an implicit side-effect, but complicates the problem of maintaining atomicity. Where the present implementation has only a do-log, the newimplementation would require support for an undo-log as well. Then the mount operation couldbe recorded in the log, to be undone should that be necessary to maintain atomicity.4.7.6 Atomicity, Distinct Machines, and ParallelismAtomicity and related matters are some of the most problematic issues surrounding the Prescription language. Atomicity is clearly an important principle, yet it has awkward ramifications as ithas been defined up to this point. The problem is that, in typical situations, errors or inconsistencies tend to be propagated upwards to the top level. Consider the situation of a set of prescripCHAPTER 4- Implementation 80tions organized in an activation hierarchy as in Figure 2. If only And blocks are involved, then astatement determined to have the value False in prescription G will cause G to be declared False,which will cause D to be declared False, which will cause B to be declared False, which willfinally cause A to be declared False. Perhaps, however, the specification given by D is partlyindependent of the specification E, and B serves a grouping purpose. In that case, processing ofB should not stop when the problem with G is detected. Also the failure of G should not necessarily cause the repair actions required for F to be skipped (or undone).Further problems arise when we introduce machine boundaries, since machines are independentin important ways. Suppose that the bubble labelled a, in Figure 2, surrounds prescriptionswhich describe the configuration of one machine, while bubble 1 surrounds prescriptions whichdescribe a different machine. In this case, we can ask whether a problem with machine a shouldprevent processing on machine 3. The problem of dealing with machines that may not be reachable has already been mentioned. The solution used in the prototype implementation is unsatisfactory.Figure 2— Activation HierarchyCHAPTER 4- Implementation 81The language lacks features for properly describing the places where atomicity is required,where machine boundaries must be ignored, and where parallelism is acceptable. Prescriptionsdo the job that they were intended to do, but they do not provide enough structure for a completeconfiguration management system. If a prescription is analogous to a procedure, then what ismissing is something analogous to a program or a package.4.7.7 Exclusivity and Change ManagementAnother tricky issue is the handling of parts of configurations that should be described exclusively. The Prescription language is primarily oriented towards inclusive descriptions. If a file isdescribed as existing in a particular directory, there is no implication that the described file is theonly file in that directory. In many situations, these are the right semantics. In other situations,the implication may be desirable. For example, consider the case of a prescription that describesprinter definitions based on entries in a database table. The general skeleton of the descriptionwould look like the following:forall P PrinterDesc $table {} {require N PrinterRecord [val $] $m.printcap {)The require statement describes the inclusion of a printer definition in the printcap table, andthe foral 1 statement therefore describes the inclusion of a definition for each entry in thetable. It does not describe the exclusion of all other entries which might exist, although that maybe desirable. It is possible to write a disallow statement that does describe the exclusion ofall printer definitions that are not based on a table entry. The problem is that such a description isawkward to write and slow to process. Worse is the situation in which different printer definitions are described by different prescriptions. It may become very difficult to write a di sal —CHAPTER 4-Implementation 82low statement that is correct. It would be much easier if a particular collection could be markedas exclusively described.The problem of exclusivity arises with specification change. Suppose, for instance, that a centraldatabase describes various printers that must be defined on machines, and prescriptions describethe machine configurations based on the information in the database. For each printer, a printcapentry must exist along with a spool directory. Now suppose that a printer is retired and notreplaced, so that the name and definition are no longer valid. It should be the case that the definitions for the old printer, in the printcap files of various machines, disappear. It should also probably be the case that the spool directories for the old printer are removed. One way to managethis would be to create disallow statements at the time when the printer is removed. Whileadding statements would achieve the desired effect, this strategy would cause descriptions togrow, over the long term, in a practically unbounded fashion. The disallow statements wouldhave to remain part of the configuration description until administrators could be sure that theyhad been processed on every machine.The situation just described seems to indicate a need for a simple procedural administrationmechanism. What would be most helpful, however, is a system capable of automatically determining the complete sequence of operations that should be performed to get from one configuration state to another. Then an administrator could simply make a central configuration change,without worrying about describing garbage that should be removed, or specifying commands toremove the garbage.The problem of automatically managing change is a significant one in a variety of software contexts. In configuration management it seems to be a major roadblock on the path towards automation.CHAPTER 4- Implementation 834.7.8 Optimizing Object SelectionThe forall and disallow statement types include selection expressions for identifying theobjects from a collection to which a statement applies. Ideally, these expressions should be ableto be used by class implementations to limit the search scope in structured collections such asthe closure of a directory. This is done in a limited way in the prototype implementation. Twoproblems arose and are explained here.The first problem is that the class implementation must be able to extract suitable informationfrom the expression. Remember that the expression is a normal boolean expression involvingthe variable declared in the statement. Extracting the right information is not an easy task in general. In the prototype, an optimization is applied only when an expression has a particular,restricted form, from which the right information can be easily removed. If an implementationused traditional parsing techniques, it might be easier to deal with general expressions. Alternatively, it might be better to leave the form of the expression entirely up to the class implementor.While that approach would simplify optimizations, it would also create a lot of inconsistency.The second problem in the prototype is that the simple form of optimization that is used (globbing through a directory structure), results in objects being “found” in the wrong collection. Asearch for a file a/b/c in directory /top is certainly fast, but if the file is found, the processingcode erroneously treats the file as being contained in the /top directory. This is a problem for thedisallow statement, since the file object might be slated for removal, and the state of thewrong collection object would then be modified.When closure processing is performed outside the class implementations, this same problemwith selection optimizations arises. An optimization may permit fast isolation of candidateobjects, but they may not all be contained in the collection under examination. The class inter-CHAPTER 4- Implementation 84face for iteration needs to be adjusted to properly handle this situation. It should provide a wayfor the class implementation to pass back a collection object with each selected object. The mainprocessing code then needs to avoid closure traversal, and rely on the class to produce the correct objects.4.7.9 Under-specified CreationThere are various kinds of objects for which creation with default values for most attributes doesnot make a whole lot of sense. The prime example of this is the symbolic link. When creation isdetermined to be necessary (in processing a require statement), only the identification of thesymbolic link is known. To create a link, however, the referent must be specified. The prototypeimplementation creates a link pointing to /dev/nufl, but it is probably better to defer creationuntil more information can be accumulated. The commit method is useful for this purpose.4.7.10 Attribute Changes that Change IdentificationSome attributes have significance in object identification. If modification to such attributes ispermitted, awkward problems may arise. For instance, a modification called for during processing of the block in a require statement might cause the object in question to fail to match theidentification value in the statement.It is common to find that the GID of an object depends upon the value of certain attributes. Ifthose attributes can be modified during repair, the possibility of a Gifi change for an object mustbe considered. Some attempt was made to prepare for this in the prototype implementation, butthe ramifications were never fully explored. It may not even be necessary for the GID to change,as long as there is no possibility that the object in question will be encountered under the newGID. This may be the situation when the object in question is an entry in a file, and cannot beCHAPTER 4-Implementation 85accessed except through the file. If the GID does not change, however, there is a possibility ofGD collision when new objects are created.4.7.11 Reference Values in TablesAs has already been described, central database tables are expected to contain fields which reference records in other tables. The getAttribute method for the TableEntry class automaticallytranslates such references to the referent object, unless the special @ syntax is employed. Thefind method on the Table class, however, does not correctly deal with object-valued key fields,so the key value must be used. Lookup by value stored is actually more efficient than lookup byreferenced object would be, but the inconsistency is disconcerting.4.7.12 Static AnalysisSince the Tcl implementation is interpreted, there is no real opportunity to perform static analysis on specifications. This is a significant limitation, as there are a number of potential uses forstatic analysis:1. Static type checking. Type checking for prescriptions would have all thebenefits of type checking in ordinary programming.2. Static identification of repairability problems.3. Static factoring of prescriptions to permit distributed and parallel processing.4.7.13 AliasesIt is common, in practical distributed systems, to use multiple names for the same entities, particularly for machines. Use of functionally meaningful names limits the scope of change when afunction is transferred from one machine to another. Extensive use of aliases, however, posessome problems for a prescription-based management system.CHAPTER 4-Implementation 86In the first place, it is important that object recognition is preserved. In the prototype, machinesand printer entries may be looked up by any alias, but the same object is always returned fornames which map to the same entity. When an aliases attribute is modified, the problem ofchanging identification, discussed in Section 4.7.10, arises.Secondly, it is sometimes awkward to organize prescriptions so that the configurations ofmachines use the correct aliases, rather than the canonical names. For instance, if a filesystem isdeclared to be exported by a machine “mainserver”, the correct Machine object must be referenced. The definition of the filesystem on any client, however, should use the alias “mainserver”regardless of the canonical name of that machine. The @ syntax described in Section 3.3.2 isuseful for solving this problem.It is not always clear how aliases ought to be handled. Entries in a printcap file, for instance,include several equivalent names. In the prototype implementation, the first one is taken ascanonical, and the others as aliases. A require statement may identify an entry by any of thenames, but if an entry is to be created, the supplied identification value will become the firstname.4.7.14 System InconsistencyThere is no guarantee that a managed system is in an appropriate state when prescriptions areprocessed. It may, in fact, be seriously damaged. The prototype implementation is not at allrobust when dealing with problems such as file format errors. It is not clear how such problemsshould be handled, but it would be nice if a configuration management system could cope withthem.CHAPTER 4-Implementation 874.8 PerformanceThe implementation described in this chapter was produced as a proof-of-concept demonstration, so performance was not an issue in the design or development. The system is extremelyslow, in fact. There are good reasons why this is so, and why it should not be a significant concern.First, the standard Tcl interpreter is not very efficient. All code, and almost all data, is maintained internally in strings. No compilation techniques are used. In a typical program, the interpreter parses and evaluates many code segments many times each. The Tcl language is achallenge to handle efficiently because of its highly dynamic nature and the extensive use ofcalls to C code in the implementation. Nonetheless, there are things that can be done to provideimpressive speed improvements. In tests presented for one compiler effort, speedup factorsbetween 1.30 (pessimistic) and 12.17 were reported [3]. There is reason to believe that evenmore impressive results could be obtained with further work.The second cause of poor performance is the nature of the prototype implementation. It is written entirely in Tcl, which means that performance is highly dependent on the interpreter. Thedata management operations involve many string manipulations, such as regular expressiontests to check whether a string contains an object reference. Finally, the implementation waswritten with much more attention to clean design than to efficient execution. Little optimizationhas been done. One way to substantially improve the implementation is to rewrite many piecesin C. The method invocation mechanism would be a good initial candidate.The poor performance that has been observed should not be a major cause of concern for a fewreasons. First, the implementation suffers from the obvious problems noted above, for whichthere are promising solutions. Also, the Tcl code could be abandoned in favour of a carefullyCHAPTER 4- Implementation 88constructed implementation in some compiled language. The most important observation is thatthe processing of prescriptions is not inherently inefficient, as can be seen by reviewing thealgorithm descriptions in Chapter 3.The main potential problem for a production implementation is the management of relativelylarge amounts of data. Given the capabilities of today’s machines, and the excellent prospectsfor distributing the work, even this problem is unlikely to be serious.895 ExperimentAny new approach to configuration management, such as the one presented in this thesis, needsto be validated by application to real-world situations. This chapter is a report on an experimental application of the new model to the configuration of client workstations in the department ofComputer Science at the University of British Columbia.The experiment tested both parts of the model presented in Chapter 2:1. The viability of the specification part was tested through the attempt toapply it to a large, real-world environment.2. The validity of the automation part was tested by running the prototypeimplementation on a significant, real-world specification.These two parts of the experiment are described separately. The chapter concludes with a unifiedanalysis of the results.CHAPTER 5- Experiment 905.1 The SpecificationTo evaluate the model and the Prescription language, a significant, practical problem wasneeded. Important aspects of workstation configuration in the Computer Science department aredescribed in a centralized database that is used by a locally developed software tool. This existing description provided an ideal test case. For the experiment, the same configuration information was expressed using tables and prescriptions. Not every detail was precisely duplicated,rather an alternate specification was produced with the same effect as the original.The first step in the translation was a careful analysis of the configuration information, to isolateabstractions and identify the appropriate units of description. Based on this analysis, a set oftables was synthesized.An example of an abstraction discovered is the logicalfilesystem. A large part of the centralizedconfiguration description is devoted to filesystems that are imported via NFS1 on clientmachines. In a number of cases, filesystems are organized into groups. All the members of agroup are imported together. One member may contain a root directory for the group, containingsymbolic links that reference parts of the other members through standardized mount points.With the Prescription model, this abstraction may be directly supported, through a table thatdefines logical filesystems in terms of individual filesystems and other data.The second step was filling the tables with the information that describes the details of machineconfigurations. In the process, various limitations of the schema were discovered and eliminated.Finally, a number of prescriptions were written, describing the configuration of the managedsystem in terms of the data in the tables. The prescriptions provide the interpretation of the1. Network File SystemCHAPTER 5- Experiment 91tables, and specify details which are common across entries. The most interesting features of thefinal specification are summarized in the sections which follow.The description consists of 14 tables (excluding the table which defines machines) and 16 prescriptions. For more detail than can be included here, refer to Appendix PrintersThe description of printers demonstrates relationship between tables and prescriptions. ThePrinter table holds entries which describe the various instances of printers. The table is definedby the following fragment (which assigns the table object returned by procedure table to thevariable Printers):set Printers [table Printer printer.table I { \name String} \tserver Machine} \{aliases List String} \{type String} \{note String} \{maxSize Integer} \} {name} }Here are a few sample entries from the table:Table 5: Printersname server aliases type note maxSizehp306 hp306 { HP 4si (in CC306) } *c.hp4s... HP 4si Roomi,CC306 CC3061w 106 1w 106 garibaldi laserwriter {NEC NEC Silent- RoomSilentwriter (in CC 106) 1) *c Writer 106nec,CC 106cicsrlw lwcicsr lp lwc default { Silentwriter (in 10000CC289) } *,CC289CHAPTER 5- Experiment 92Table 5: Printersname server aliases type note maxSize1w238 1w238 clinker clink *,CC238 NEC Silent- DraftWriter Room312The following prescription describes the configuration of a client machine which will haveaccess to a printer defined in the table above.# PrinterDef - describes a remote printer definition that# must be present on a machine## Parameters:# m : Machine# pd : Printer (from table)#prescription PrinterDef {m pd} {global Allnarrow { or {require M Machine [val $] $All Urequire M MachineProxy [val $] $All U}}if { [strEQ $ $] }# Printer should be locally defined on its server} else {# A PrinterEntry must existrequire P PrinterRecord [val $] $m.printcap {logical $ s= $pd.namelogical $P.aliases s= $pd.aliaseslogical $P.lp s=logical $P.rm s= $pd.serverlogical $P.rp s= $pd.nameif { [strEQ $pd.maxSize “1 )logical $ == 0} else {logical $ == $pd.maxSizelogical $ s= /usr/spool/print/[val $]logical $P.ty s= $pd.typelogical $P.note s= $pd.note# The specified spooi directory must existCHAPTER 5- Experiment 93global root daemondir $m $ $daemon $daemon 02755}}The prescription describes two things. First, it describes the printcap entry, which defines theprinter to the client machine. Second, it describes a spooi directory which must exist. Note thatthe prescription specifies values for some fields of the printcap entry that do not change fromprinter to printer (in this organization). Also, some values are derived from values given in thetable. For instance, the spool directory path is derived from a standard root and the name of theprinter. Administrators do not have to enter a spool directory for each printer they define, andthey have assurance of consistent naming. Another important feature of the prescription is thefact that it can be safely applied to a machine which happens to be the server for the printer.The PrinterDef prescription relies on a prescription called dir, defined as follows:## dir - describes a directory that must exist# Parameters:# m : Machine on which dir must exist# path : String pathname of directory# owner : Integer owner uid# group : Integer group gid* mode : Integer permission modeprescription dir {m path owner group mode} {require D Directory $path -closure $m.root {logical $D.owner $ownerlogical $D.perms == $modelogical $ == $group}}A separate prescription is used because directory existence is specified in a number of contexts,and the prescription can be easily re-used. This is a simple example of the value of modularity.CHAPTER 5- Experiment 945.t2 FilesystemsThe descriptions of filesystems and related items are considerably more complicated than thedescriptions of printers.A table describes individual filesystems that may be imported via NFS. The table records, foreach filesystem, a name, a server, the path of the filesystem on the server, indications of whethersoft mounting and quotas are required, a canonical name under which the filesystem should beaccessible on the client (optional), a mountPoint (optional), and an indication of whether thenamespace of the server should be made canonical.A few prescriptions are involved in the description of importing a single filesystem. Most of theconfiguration does not apply on the machine which is the server for the filesystem, butnamespace canonicalization does. To canonicalize a namespace, symbolic links must be used. Ifa canonical name is given for a filesystem, a link with that name is specified to point to themount point of the filesystem. Supplementary tables contain entries that describe arbitrary linksto be made into the filesystem, and sets of links to particular directories based upOn the architecture of the importing machine. The fstab entry that is required for the filesystem is described, asis the existence of the mount point directory. If the mount point is unspecified in the table, then aprescription defines one according to a simple formula, in the same way that a printer spooldirectory is defined. The mount options are partially determined by the values given for the softmount and quota fields in the table. The original configuration description includes alternateserver aliases to be used by clients on particular subnets. These details are accommodated in asupplementary table that contains the name to be used for various server/subnet pairs.As described earlier, the abstraction of logical filesystems is supported by a table that describesfilesystem groups. Each group has a name, a list of filesystems that are part of the group, anCHAPTER 5- Experiment 95(optional) indication of the filesystem that holds the root directory, an (optional) path to thatdirectory within the filesystem containing it, and an (optional) canonical name by which the rootdirectory should be accessible.The prescriptions describe the import of a logical filesystem in terms of the import of each of theparts, plus the existence of an appropriate symbolic link for the root directory, if there is a rootdirectory.5.1.3 Services, Groups, and AssignmentsTo complete the specification, there are tables defining groups of machines, groups of services,and the assignment of services to machines and groups of machines. Both groups of machinesand groups of services can contain other groups of the same type, so there is a lot of organizational flexibility.A service group is composed of other service groups, printers, individual filesystems, and logical filesystems. In addition, a service group may be limited to a particular architecture. There arealso supplementary tables which describe directories, symbolic links, and file copies that mustexist when a service group is assigned to a machine.Here is the top-level prescription describing the entire configuration, based on the tables and theother prescriptions which are defined:* main - describes state of entire distributed system## The use of the name ‘main’ is arbitrary.* The appropriate state is described in various tables.* This prescription consists of assertions about the# system in relation to the data in various tablesprescription main {} {global ServiceAssignCHAPTER 5- Experiment 96forall S ServiceAssignment $ServiceAssign {}# Each service is assigned to the specified group of machinesAssignToGroup $ $S.service* Each service is assigned to the specified individual machinesforall M Machine $S.individual {} {AssignServices [Machine $M] $S.service}global MachineAssign* Each machine has the specified individual services assignedforall M MachineAssignment $MachineAssign {}forall S ServiceGroup $ UAssignServices [Machine $M.machinel $S}forall L FilesystemGroup $M.logicals UImportGroup [Machine $M.machinej $Lforall F Filesystem $M.filesystems {}Guardedlmport [Machine $M.machine] $F)}The configuration of most machines is derived from the groups in which the machines areplaced. The prescriptions for printer and filesystem definition have special cases for servers. Thereason for these is that a server may be part of any group, so it may end up being assigned a service which it provides. A server should not be configured to import a service from itself. Theprescriptions handle servers automatically, so special measures do not need to be taken toexclude them from certain groups or assignments.5.2 The ProcessingIn the second part of the experiment, pieces of the specification described above were testedusing production workstations and the prototype implementation.Initially, trials were conducted with small, distinct bits of specification. For example, the dirprescription presented earlier was activated with various combinations of values for the parameCHAPTER 5- Experiment 97ters. Consider the following example, in which the prescription is used to verify the existence ofthe directory /usrfbin, with standard permissions and ownership:mytcl>activate { dir $san /usr/bin $root $staff 02755 }TrueIn this example, the variable san contains an object representing a machine. The variablesroot and staff hold the ids of the root user and staff group. The string “mytci>” is theinteractive prompt of the interpreter. The word True is the response of the implementation indi-cating the truth value that was determined. With a slight change, the statement becomes False:mytcl>activate f dir $san /usr/bin/ $root $daemon 02755 }FalseLogical false for <Directory> /usr/bin>.groupvalue=<2000>op=<==>compareVal<l>Prescription Activation Stack:0: Prescription “activate” : <Top level>1: Prescription “dir” : (Machine <>} /usr/bin/ 0 1 02755Statement and {require D Directory $path -closure $m.root (logical $D.owner == $ownerlogical $D.perms == $modelogical $ == $group}Statement and {logical $D.owner == $ownerlogical $D.perms == $modelogical $ == $group}In this case, the implementation produces additional information to help pinpoint the discrepancy between the specification and the managed system.CHAPTER 5- Experiment 98Gradually, more and more extensive specifications were processed. The trials revealed variousproblems and implementation bugs which were addressed along the way. Finally, two major trials were conducted, as described in the following two sections.5.2.1 Setup TrialThe code for the Machine class was modified slightly to treat a test directory (Itmp/RJ) as theroot directory of a machine. The experimental directory tree was populated with just a few basicfiles and directories, on one slave machine. For instance, an /etc/fstab file was created, containing only comments and the definitions of local filesystems. The prescription main was thenactivated for repair mode processing on a master machine distinct from the test slave. The testwas designed to simulate a situation in which a new machine is configured. The resulting logcontained 999 individual repair actions. Here are the first few records from the log:Create new object <Directory> /tmp/R//nfs>Create new object <Directory> /tmp/R//nfs/facuityl>Set <Directory>ice.cs.ubc .ca: /tmp/R//nfs/facultyl> attribute <group> to<0>Create new object <FileSysRecord <facultyl,/facultyl> in /tmp/R/etc/fstab>Set <FileSysRecord <facultyl,/facultyl> in /tmp/R/etc/fstab> attribute<dir> to </nfs/facultyl>Set <FileSysRecord <facultyl,/facultyl> in /tmp/R/etc/fstab> attribute<type> to <nfs>Set <FileSysRecord <facultyl,/facultyl> in /tmp/R/etc/fstab> attribute<options> to <rw>Set <FileSysRecord <facultyl,/facultyl> in /tmp/R/etc/fstab> attribute<options> to <rw intr>Set <FileSysRecord <facultyl,/facultyl> in /tmp/R/etc/fstab> attribute<options> to <rw intr bg>Create new object <SymLink> /tmp/R//facultyl>Set <SyrnLink>> attribute <ref> to </nfs/facultyl>These particular records cover the operations required for the machine to import the faculty 1filesystem, which is a part of the faculty filesystem group. Note that five of the operationsinvolve the fstab entry that is required for the filesystem. The references to paths beginning withCHAPTER 5- Experiment 99“/nfs” appear because the table data and prescriptions were not updated to use /tmpIRJ as theroot directory.Finally, the recorded operations were executed to carry out the repair. The implementation skipsoperations which require privilege, but the necessary directories, links, and file copies were created. Also the fstab and printcap files were updated with the required definitions. Comments thatexisted in the files prior to repair were not preserved, because the implementation does not support comments.5.2.2 Verification TrialThe prescription main was activated for repair mode processing on a master machine with twoengaged slave machines. Due to the fact that there were differences between the experimentalspecification and the configuration of the machines, a number of repair actions were logged forboth machines. The logs clearly identified the ways in which the actual configurations deviatedfrom the specification. Execution of the operations specified in the logs would have repaired themachines to match the experimental specification. Many of the deviations were due to the factthat the experimental specification uses a slightly different convention for naming mount pointsthen is used in the original configuration description.5.3 EvaluationThe experiment was successful. A specification was produced for a substantial, real-world system. The prototype implementation processed the specification in multiple ways. The experiment was certainly not exhaustive, but did test the essential features of the model that ispresented in this thesis.The evaluation is not complete with the conclusion that the experiment was a success. A numberof more interesting observations can be made. To begin, we can compare the new approach toCHAPTER 5- Experiment 100the existing technology. The configuration description that was used as a basis for the experiment is input to a locally developed tool called TANIS [10]. The TANIS program is a shell scriptwhich configures a machine based upon the configuration description, which is distributed viaNIS1.The description has a simple form, and includes the complete text of entries to be placedin fstab and printcap databases. TANIS is a good example of a simple tool developed by systemadministrators to meet local needs.The TANIS and Prescription specifications are comparable in size. The TANIS specificationconsists of nearly 1200 records, with a total size of about 55K including no comments2.Over900 records (around 47K) are devoted to describing individual pieces of configuration, asopposed to structure and assignment. Excluding machine names, the TANIS specificationincludes definitions of nearly 200 names to identify pieces of specification, and groups of services. The experimental Prescription specification contains a total of 1164 non-blank records,with 433 of those spread across 13 tables, and 597 in definitions and prescriptions. When comments are removed, the grand total drops to 934 records. The tables contain around 20K of data,and the definitions and prescriptions add around 18K including comments. The Prescriptionspecification includes definitions of slightly more than 200 names. Note that the size values aredependent on the details of the syntactic forms.The two specifications are largely equivalent, but they do not match exactly. Many specifications of directory attributes that are part of the TANIS description were not explicitly duplicated.Also, a few pieces of the TANIS description which are inconsistent or obsolete were not translated.1. Network Information System.2. The size information given here does not include machine information or machine group informationfor either specification.CHAPTER 5- Experiment 101Comparative evaluations between the two systems can also be made on a number of qualitativepoints. Those that tend to favour the Prescription approach are presented first, followed by thosethat favour the existing TANIS form.5.3.1 Prescription AdvantagesNo Repetition of DetailA TANIS description necessarily involves substantial repetition of common details, due to thefact that the complete text of table entries is included. For example, in the original descriptionthere are 112 occurrences of the string “rw,bg,intr” in filesystem definitions, and 233 occurrences of “root.wheel 755” in directory descriptions. In the Prescription model, common detailsare placed in prescriptions, where they do not need to be written multiple times, so each of “rw”,“bg”, and “intr” appear only once and the equivalent of “root.wheel 755” appears only 4 times.Special Case SupportSpecial handling for servers in the Prescription case has already been mentioned. In the TANISdescription, servers must be protected from importing their own services, by explicit subtractions (of which there are some 54). This places a burden on those who maintain the description,because they must remember to adjust subtractions when they make other changes. In the Prescription case, the protection problem can be solved once and for all when the prescriptions arewritten.AbstractionWith TANIS, structural abstractions are mostly implicit. For example, each link required forarchitecture-specific namespace adjustment must be specified explicitly, although they alwaysoccur in standardized groups. The Prescription model supports abstractions more explicitly. ForCHAPTER 5- Experiment 102the case of architecture-specific links, it is possible to specify only the source location of a groupin each instance, while a prescription describes the individual links for a group in general.Consistency MaintenanceWith TANIS, all consistency constraints must be manually preserved. Due to the lack of abstraction support mentioned above, common features must be duplicated for each instance of something. For example, if a decision is made to name printer spool directories a certain way, basedon the printer name, an administrator must remember to do this correctly every time a printer isadded. The Prescription model, however, is designed to permit common details to be encapsulated in prescriptions which change infrequently. The details of instances are specified separately. In the printer example, the spool directory name is derived from the printer name in aprescription, and printers can be added without any consideration of spool directory name at all.Thus it is easier to maintain specifications in the first place. Also, a Prescription implementationwill inherently permit automated checking of instance data consistency, which TANIS does not.UnderstandabilityTANIS descriptions are difficult to understand due to a lack of internal documentation, the factthat organization and relationships are mostly implicit and maintained by convention, and thefact that there is minimal typing. The Prescription approach supports comments in prescriptions,tables that meaningfully organize instance data, explicit inter-table relationships, and greatertyping. On the other hand, prescriptions define things in much more abstract terms than theentries in a TANIS database, and the mapping from the specification to the syntax of the systemis much less transparent.Architecture IndependenceMany parts of a TANIS specification are expressed using the precise syntax of the managed system. In the Prescription model, an abstract form is used. As a result, a Prescription specificationshould be more portable than a TANIS one.CHAPTER 5- Experiment 1035.3.2 TANIS AdvantagesAggregation ConvenienceIn the Prescription specification, records and fields in tables are typed, so a service cannot bedefined to include multiple types of things without having intermediate names for each of thepieces. TANIS has almost no concept of typing, so it is easy to define a single name which justhappens to have filesystem, printer, and directory definitions associated with it. The Prescriptionform is more structured, and therefore is more inconvenient. On the other hand, the Prescriptionapproach does enforce consistency.Unconstrained FlexibilityWith TANIS, the form imposes no restrictions so there is always complete flexibility. With thePrescription model, once the tables and prescriptions are established, the flexibility is strictlylimited. New situations that were not envisioned when the tables were defined may requireschema modification. For example, suppose that tables were originally designed based on adecision that spool directories should always have the same ownership and permissions. If thedecision changed, a table structure would need to be modified, various prescriptions would needto change, and entries for all existing printers would need to be updated. With TANIS, the decision to use consistent permissions would be a convention only, and a change to accommodate anew situation would not impact older parts of the specification.104CHAPTER 6 Related WorkThe problem of software configuration management has been studied in a variety of contexts.This chapter presents just a few systems which are particularly related to the work in this thesis.Almost all of the systems described here are very practical, in keeping with the focus of this thesis.6.1 RCMSThe Raven Configuration Management System (RCMS) [4] is a system developed at UBC aspart of an exploration of configuration management in general. RCMS supports management ofcollections of objects in the Raven [5] object-oriented system. Specifications of correct configurations are given as assertions in the first-order predicate calculus. The predicate calculus is apowerful, declarative formalism. Since the descriptive language is so powerful, it is hard for anautomated system to determine what actions should be taken when the specifications are violated. A user of the RCMS must write short repair programs to accompany specifications. A colCHAPTER 6- Related Work 105lection of managed objects is monitored by RCMS, and a repair program is executed wheneverthe monitoring detects a violation of a specification.The RCMS work was an major inspiration for this thesis. The basic notion of describing configurations declaratively in terms of objects comes directly from RCMS. The model presented inthis thesis, however, addresses the specific problem of practical workstation configuration.Unlike RCMS, the target environment is not a uniform object-oriented distributed system, repairis entirely automated, and specifications are more highly structured, involving two parts.6.2 MoiraThe Moira system [6), from the Athena project at MIT, is directed at the problem of automatingmaintenance of the many pieces of data which parameterize configurations of typical workstations. Data about various services is maintained in a central database. The Moira software iscapable of generating the operational files required by the various services, in the correct formats, from the central database. The system also handles distribution of files to client machines.Moira demonstrates that the management of data does not have to be limited by the idiosyncratic formats required by operating systems. The idea of structured specifications includingdatabase tables was inspired by Moira. In Moira, however, the transfer of data from the databaseinto various configuration files is performed by special programs. The use of prescriptions permits a more general system to be developed.Moira provides automation with abstraction and structure, but does not help with verificationand is less than transparent. It does not support much automated consistency/correctness checking. Without such checks, Moira may distribute erroneous data which prevents the system fromworking to deliver corrections. This problem demonstrates the value of consistency checks inspecifications.CHAPTER 6- Related Work 1066.3 DepotThe Depot system [7] is designed to maintain third party and locally developed software inlarge, heterogeneous environments. The goal is integration of separately maintained packagesinto a common directory hierarchy without increasing dependence on central servers. Configurations may be specified in a number of ways:1. Listing specific collections and paths to their location.2. Providing search paths where the first instance of each collection within apath will be used.3. Placing collections in a special directory4. Using a combination of the above methodsDepot is capable of performing some consistency checking according to simple fixed rulesbased on the application. Support is also provided for moving collections of software around,which is a significant practical matter which is not addressed in this thesis. The claim is madethat simple mirroring of directory hierarchies, plus simple options, are easy for both administrators and developers to understand [7, p. 157].Depot is a good example of a tool which primarily addresses the problem of replicating a configuration on a large number of systems. Unfortunately, it is narrow in scope, with a verylimited specification language. It does not provide any assistance with verification, and does notfeature abstraction.6.4 HobgoblinThe hobgoblin [8] system is a file and directory auditor. The tool was created to automaticallycheck conformance of systems to abstract models. The abstract model is expressed by listingfiles and directories and their properties. Operators are provided to state that a particular file orCHAPTER 6- Related Work 107directory must exist, may exist, or must not exist. In addition to existence, the language permitsspecification of properties of files through “attribute checkers”. The attributes which may bespecified are mode, owner, group, size, symlink reference, and dates. The list may be expandedthrough addition of external checkers. There is explicit support for describing contents of directories exclusively, and nesting is supported in descriptions. Finally, there is a “delta” language,for expressing a specification as a variation of another specification. An interpreter is capable ofchecking systems for conformance with hobgoblin specifications.The hobgoblin system demonstrates a practical use of declarative descriptions for verification.Unfortunately, hobgoblin has two limitations which prevent its use for more general administration. First, the specification language only handles things of one kind (files). Second, the tool isdesigned only for checking conformance to specification. It cannot be used to set up a system.The designers have clearly considered removing the second limitation, as they mention a notionof “enforcers” which would modify files to achieve conformance to specification.The Prescription language is similar in descriptive power to the language used by hobgoblin, butis more general, and permits automated repair as well as verification.6.5 DoitThe doit solution [9] is a network software management tool designed to automate the management of software configurations on large numbers of machines. Unlike hobgoblin, doit isintended to set up machines, not check them for correctness. The specification language is procedural. Three types of actions may be performed: addition of software, deletion of software,and execution of arbitrary commands. There are variants of each type of action which causerebooting of a host after some number of steps are performed. The system uses revision levels tokeep track of what has been done on a particular machine. Each action has an associated reviCHAPTER 6 - Related Work 108sion level. There are also special levels for actions that should be performed at the start or end ofeach run. Configurations for doit are assigned to groups of machines. The groups are declaratively specified using set logic.The problem with a procedural form of specification is that it generally precludes any checking.Records of the state of each machine become very important in this case, and troubleshootingmay be difficult. The model presented in this thesis relies on declarative specifications to simplify checking. Doit lacks the verification, abstraction and synchronism features of the model,but does have better facilities for record-keeping and software installation.6.6 TANISThe locally developed system called TANIS (Tagged Attribute Network Information Service)[101 was described in Chapter 5. TANIS is a lot like doit. A “service definition” can consist of afew forms of specification: description of a directory to be created, description of asymbolic link to be created, entry for a filesystem table, entry for a printer table, description of afile that should be copied, etc. Note that most of these are declarative, although no TANIS software is presently capable of checking conformance. Variables may be incorporated in specifications to achieve machine-independence.TANIS provides flexible automation, but is limited in scope, and lacks any abstraction. It alsolacks the structure for avoiding repetition, and does not provide any synchronism. A more complete comparison of the TANIS and Prescription specification forms is provided in Section 5.3.109CHAPTER 7 ConclusionsThis thesis has explored a general approach to automating some aspects of configuration management, in typical distributed computing environments. The thesis has demonstrated that a general framework is suitable as the basis for automating tasks of practical importance.Declarative description is an ideal form of input for automated management tools. Descriptionsare the natural way to express configuration information. They are well suited to the tasks ofverification, monitoring, and analysis. At the same time, the use of descriptions does not necessarily preclude efficient automated repair, as has been demonstrated.7.1 Review of ContributionsThe thesis presented a model for automating practical configuration management, a novel language for describing configurations, a prototype implementation, and a significant experimentthat validates the work. Each of these specific contributions is reviewed here.CHAPTER 7- Conclusions 1107.1.1 A Model of Configuration ManagementA general model was proposed, based upon features of the problem. The model is practical, butis also abstract and flexible through the use of objects to model components. Its primary characteristic is reliance on declarative forms of specification for both verification and repair purposes.It features a structured specification model, in which common, structural pieces of descriptionare written in a logic language, and varying details are expressed separately in a database.7.1.2 The Prescription LanguageThe Prescription language was introduced as the vehicle for structural specification in the newmodel. The language provides a reasonably simple declarative formalism, carefully designed tobalance the competing requirements of verification and repair. It offers modularity and otherfeatures of traditional imperative programming languages.7.1.3 A Prototype ImplementationThe implementation proved that the Prescription language can be implemented. Production ofthe implementation produced a number of insights into the challenges of automated configuration management using an object abstraction.7.1.4 An ExperimentThe experiment demonstrated the successful application of the model and language to some ofthe practical problems of configuring a real computing environment. The configuration of alarge group of machines was described using a simple database and a set of prescriptions. Theprototype implementation successfully performed automated verification and repair based onthe resulting specification.CHAPTER 7- Conclusions 1117.2 Future WorkThe work in this thesis is really just a preliminary step towards the goal of general automation ofconfiguration management. Ultimately, distributed systems should be built with intrinsic management facilities. Much more work needs to be done in order to completely identify the set offacilities which will be required. There a number of obvious avenues that could be pursuedbased upon the work in this thesis.7.2.1 Addressing Open ProblemsA number of the issues and problems introduced in Section 4.7 deserve further research. Theproposed scheme for dealing with dependencies on implicit side-effects has not been implemented or tested, and the whole issue of implicit side-effects requires further study. The handling of atomicity and machine boundaries certainly needs work. A production implementation,based on compiler technology and featuring static analysis of specifications, would be useful.7.2.2 Stretching the ModelThe model needs to be stretched through application to different sorts of problems. One problemof particular interest is the software installation/de-installation problem. It should be possible towrite prescriptions describing a configuration of a managed system in which a piece of softwareis properly installed. Such a set of prescriptions would ideally encapsulate all the installationinformation that is required, so that installation can be done (at least partially) by automatedrepair. It is likely that the model of this thesis is not adequate, as it stands, for solving the installation problem.It would also be interesting to use declarative specifications to describe user environments,involving such things as the contents of environment variables.CHAPTER 7- Conclusions 112The absence of a larger context for prescriptions was mentioned in Section 4.7.6 and deserveselaboration. Some structure is needed for groups of related prescriptions. Such a structure couldincorporate means of identifying which prescriptions should be used in different situations. Forinstance, in a set of prescriptions describing a software package, there might be one describingwhat the package requires from the operating system, one describing the properly installed state,one describing the properly de-installed state, one describing the conect operational state at anytime during use, and one describing the user environment required for the package. Other prescriptions might be for internal use of those described above. All would rely upon a commoncollection of site-specific data.7.2.3 Improving RepairVarious approaches could be taken to increase the power and utility of automated repair. Forinstance, it might be useful to permit repair hints in specifications. Hints could be used to indicate which of a set of possible repair strategies is the appropriate one in a given situation. ThePrescription language supports implicit hints: the choice of statement includes an implicit hintabout the repair strategy to be used. Subclassing is one way of providing different repair algorithms for different situations.Another possible way to extend automated repair would be to add a more powerful solver. Thisidea was discussed in Section 3.8.3. Use of a search-oriented solution engine would introduceconsiderable complexity and reduce efficiency, but it might be possible to limit the negativeimpact.For some situations, fully automated repair is simply not feasible. Thus it may be helpful to permit repair scripts to be composed to complement declarative specifications. Adding proceduralCHAPTER 7- Conclusions 113repair would be a significant adjustment to the model. Care is needed to avoid undermining thevalue of declarative specifications.7.2.4 Adding DynamiclTemporal SupportThe Prescription language has no support for temporal assertions. This is one limitation whichmight cause problems for more dynamic configuration management situations. Automatedrepair in dynamic situations with temporal specifications is likely to be quite problematic.7.2.5 Adding Consistency CheckingIt is possible to specify a variety of consistency constraints using the Prescription language, andto have them checked by the prototype implementation. For instance, it is possible to expressconstraints on the data in tables, and have the implementation identify cases where the constraints are violated.The thesis does not address the problem of automatic detection of inconsistencies between partsof a complete specification. For instance, it is possible to write a prescription that simultaneously requires a file to have two different permission settings. Such a prescription is unlikelyto occur in practice, but there are more subtle variations of the same problem. Prescriptions fromdifferent sources might be combined to describe a system, and there might be conflicts betweenthem. A good example of this would be the case of prescriptions describing installation of twodifferent software packages. A configuration management system needs to be capable of detecting such conflicts automatically.7.2.6 Improving Support for ChangeThe model that was presented does not adequately address the difficulties associated with variations in configuration over time. This limitation was explained in Section 4.7.7 in some detail.CHAPTER 7- Conclusions 114As noted there, the problem of dealing with change appears to be a problem that will be verysignificant for automated configuration management. At a minimum, a configuration management system needs capabilities for recording what is done, and undoing it. Ideally, a systemshould be able to automatically determine what operations need to be performed to move fromone configuration state to another, including cleanup operations.7.2.7 Adding SecurityThe model that has been presented does not address security, authentication, or authorization. Inpractice, basic security is an important issue. A more significant research problem is the fact thatin many real-world environments, the authority to determine the configuration of a machine maybe shared by different people or groups. Some may have the right to control only certain aspectsof system configuration.115Glossaryactivated - The state of a prescription which is being processed by a configuration management system.class- The definitional unit corresponding to a type of component. Every object is aninstance of some class.collection - A component (or an object which models one) which collects other components. For example, a directory is a collection because it collects files. The contents of collections in a managed system are an important part of the configurationstate of the managed system.component - Any distinguishable piece of a managed system, whether hardware object - An collection of data with associated operations. This term has the meaning normally associated with the term object, in object-oriented programming.deferred execution - The implementation scheme in which repair processing is split intotwo phases, separated in time. In the first phase, the sequence of operations to beperformed is determined and recorded. In the second phase, the sequence is actually executed. In between the phases, the record (or do-log) may be reviewed and!or modified.dependent attribute- An attribute, of an object, whose value is dependent on the valuesof other attributes, and cannot therefore be modified without impacting the valuesof other attributes.descriptive adequacy - The property of a specification formalism that holds if the formalism is able to be used to describe any configuration state which the managedsystem may A record of operations yet to be performed.exclusivity - The property of a specification that holds if the specification describes theconfiguration of a component completely, whether implicitly or identifier - A value which uniquely identifies a component of a managed system(and also the object that represents it).116immutable attribute - An attribute, of an object, whose value is not modifiable duringrepair processing due to some property of the object andlor modelled component.inclusivity - The property of a specification that holds if the specification describes theconfiguration of a component incompletely, so that multiple configurations mayconform to the specification.instance data - Data about a particular instance of something, such as a name. Also usedto refer to the data stored for an object and accessible to the object implementation.logical filesystem - An abstraction providing the appearance of a single, unified filesystern through multiple actual filesystems and symbolic links.managed system - A collection of items, composing a system, managed by an automatedtool or collection of tools. A managed system can include both hardware and software items.master machine - The central machine that is designated to process prescriptions.narrowed - The condition of a statement which is to be processed in verify mode, regardless of the prevailing mode. The term is also applied to prescriptions which aredefined such that every activation will be narrowed.narrowing - The processing step of restricting the mode to verify mode in the course ofprocessing a narrowed statement.object - An abstraction representing a component of a managed system. An object hasattributes whose values represent different aspects of the configuration state of therepresented component.Object layer - The set of procedures that implement the centralized record-keepingwhich supports deferred execution.object recognition - The process of determining whether or not an object already existsto represent some component.prescription - a named, parameterized piece of specification in the Prescription language.A prescription is the unit of definition in the language, and is similar to a predicateor - The process of modifying a managed system so that it has a specified configuration. Repair includes identification of discrepancies between the system and thespecification, determination of a sequence of operations that can be performed toeliminate the discrepancies, and the execution of that sequence of operations.repairable - The property of a Prescription statement that holds if the statement is suitable for automated repair.117repair mode - A Prescription processing mode in which the configuration managementsystem will proceed with repair as discrepancies between a specification and amanaged system are identified.slave machine - Any machine, other than the master, which is part of a managed systemand must be accessed during prescription processing.truth value - A boolean value which represents the conformance of a managed system tothe specification given by a Prescription statement, at a particular point in time.undo-log - A record of operations which have been performed but which may need to bereversed.verification - The process of comparing a configuration specification against a managedsystem to determine whether the managed system has the specified configuration.verify mode - A Prescription processing mode in which no repair is attempted.118Bibliography[1] John Ousterhout. Tcl and the Tk Toolkit. Addison-Wesley Publishing Company, Reading Massachusetts, 1994.[2] Lawrence A. Rowe and Brian C. Smith. Tcl-DP, online manual.[3] Adam Sah and John Blow. A Compiler for the Tcl Language. TCLITK Workshop, Berkeley, June1993.[4] Terry Coatta and Gerald Neufeld. Distributed Configuration Management Using CompositeObjects and Constraints. Second International Workshop on Configurable Distributed Systems,Pittsburgh 1994.[5] Gerald Neufeld, Don Acton, and Terry Coatta. The Raven System. University of British Columbia,1992. Computer Science Technical Report TR-92-15.[6] Mark A. Rosenstein, Daniel E. Geer, Jr., and Peter J. Levine. The Athena Service ManagementSystem. Usenix Conference Proceedings, Winter 1988.[7] Wallace Collyer and Walter Wong. Depot: A tool for Managing Software Environments. Proceedings of the Sixth System Administration Conference (LISA VI), page 153, October 1992.[8] Kenneth Rich and Scott Leadley. hobgoblin: A File and Directory Auditor. Proceedings of thefifthLarge Installation Systems Administration Conference, page 199, September 1991.[9] Mark Fletcher. doit: A Network Software Management Tool. Proceedings of the Sixth SystemAdministration Conference (LISA VI), page 189, October 1992.[10] Mark Majka and George Phillips. tanis- systemfor boot-time machine configuration. Universityof British Columbia. Computer Science online manual.[11] Marshall T. Rose. The Simple Book An Introduction to Management of TCP/IP based internets.Prentice Hall, Englewood Cliffs New Jersey, 1991.[12] ISO/IEC IS 9595. Information Technology- Open Systems Interconnection- Common Management Information Services Definition (CMJS), 1991.[13] ISOIIEC IS 9596-1. Information Technology- Open Systems Interconnection- Common Management Information Protocol- Part]: Specification (CMIP), 1991.119Appendix ASpecification DetailsMost of the prescriptions produced for the specification experiment were not included in Chapter 5 in the interest of brevity. The definitions and prescriptions are included in their entiretyhere. The following trivial modifications have been made from the version used in the experiment:1. Comments have been modified slightly.2. Statements designed to produce output during processing have beenremoved.3. Spacing has been modified slightly.Apart from these differences, the code presented here is identical to that which was actually processed by the prototype implementation.Note that the ArchDirs prescription was never processed (the activation in ImportSupplemental is commented out). This is because of the problem that the prescription dependson implicit side effects, as described in Section 4.7.5.The contents of the various tables are an important part of the total specification. Those contentsare not included in this thesis because they would not be helpful to anyone unfamiliar with thedepartment configuration, and they would consume a lot of space. A few entries from one tableare included in this appendix, to illustrate the relationship between the table definitions and thecontents of the files.120Al Experimental Specification Definitions# Initial Setup: load class definitions, etc.#import file.tclimport fstab.tclimport printcap. tcl# Define the machines#set Machines [table MachineDesc machine.table I ( \(name String} \(aliases List String) \{arch String) \(subnet Integer) \} (name) {)]set All [machine $Machines]# Define tables4set MGroups [table MachineGroup mgroup.table I { \(name String) \{subgroups List MachineGroup) \(members List Machine) \(name) ()set ServiceAssign [table ServiceAssignment assign.table I ( \(service ServiceGroup) \(group MachineGroup) \{individual List Machine) \) (} ()set SGroups [table ServiceGroup sgroup.table I ( \(name String) \(subgroups List ServiceGroup} \(arch String) \(printers List Printer) \{filesystems List Filesystem) \{logicals List FilesystemGroup} \) (name) ((ServiceLink (name service)) \(ServiceFileCopy (name service)) (ServiceDir (name service)))set Exclusions [table MachineExciude exclude.table I { \(machine Machine) \{noimport List Filesystem) \{noimportgroup List FilesystemGroup} \(reject List ServiceGroup) \) (machine) () I121set MachineAssign [table MachineAssignrnent massign.table I ( \(machine Machine) \(services List ServiceGroup) \(filesystems List Filesystem) \(logicals List FilesystemGroup) \} (machine) () Iset Alternates [table ServerAlternate server-alt.table I ( \(server Machine) \(subnet Integer) \(alternate String} \(server subnet) {} Iset FGroups [table FilesystemGroup fgroup.table ( \( name String) \(parts List Filesystem} \(root Filesystem} \(rootName String} \{rootCname String) \} (name} (} Iset FS [table Filesystem fs.table ( \(name String) \(server Machine) \(fs String) \(soft Boolean} \{quota Boolean} \{cname String) \(mountPoint String) \{canonicalize Boolean) \{name} {{FilesystemLink (name fs}} (FilesystemArch (name fs)))set FSLinks [table FilesystemLink flink.table I { \{fs Filesystem) \(source String) \(link String) \} {} {) Iset FSArch [table FilesysternArch arch.table ( \(fs Filesystem} \(source String) \(link String) \{subdirs Boolean} \) {) (}set Printers [table Printer printer.table I ( \(name String} \(server Machine) \(aliases List String} \{type String) \(note String) \122{maxSize Integer) \} (name) U Iset SLinks [table ServiceLink slink.table I ( \(service ServiceGroup) \(source String) \(link String) \) {} (I Iset FileCopies [table ServiceFileCopy copy.table I { \(service ServiceGroup} \(name String) \(source String) \(dest String) \) (} () Iset Dirs [table ServiceDir dir.table { \(service ServiceGroup} \(dir String) \) (} (} I# Global constantsset root 0set daemon 1set wheel 0## Prescriptions## main - describes state of entire distributed system* The use of the name ‘main’ is arbitrary.# The appropriate state is described in various tables.# This prescription consists of assertions about the* system in relation to the data in various tablesprescription main () (global ServiceAssignforall S ServiceAssigrunent $ServiceAssign {}# Each service is assigned to the specified group of machinesAssignToGroup $ $S.service# Each service is assigned to the specified individualmachinesforall M Machine $S.individual {) (AssignServices [Machine $M] $S.service}123global MachineAssign# Each machine has the specified individual services assignedforall M MachineAssignment $MachineAssign {}forall S ServiceGroup $ {}AssignServices [Machine $M.machine] $S}forall L FilesystemGroup $M.logicals {} fImportGroup [Machine $M.machine] $Lforall F Filesystem $M.filesystems {}Guardedlmport [Machine $M.machine] $F}}I# AssignToGroup - Describes the assignment of# a group of services to a group of machines#* Parameters:* mg : MachineGroup (from table)* sg : SérviceGroup (from table)prescription AssignToGroup {mg sg} {# The group of services is assigned to machines in* subgroups of the group of machinesforall M MachineGroup $mg.subgroups {} tAssignToGroup $M $sgI# The service group is assigned to individual machinesforall I Machine $mg.members {} {Assignlndividual [Machine $1] $sg}#* Assignlndividual - Describes the assignment of a# group of services to an individual machine## Parameters:* m : Machine - the machine to which assignment is made# sg : ServiceGroup - entry in table# This prescription accomodates two special cases:* 1) A group of services may be defined for machines of a particular* architecture only. If this is the case, the ‘arch’ attribute* will contain the name of the architecture. Otherwise, the* attribute will be empty, and the services are to be applied# to all machines.124# 2) A group of services may not be desired on a particular machine# even though the machine might normally qualify for the services.# This exceptional case is described by an entry for the machine# in the Exclusions table, with the ServiceGroup listed in the# ‘reject’ attribute.prescription Assignlndividual {m sg} {# When ServiceGroup is architecture specific, it only# applies to machines of the correct typeif { [string length [val $sg.archj I == 0[strEQ $sg.arch $m.arch] } {global Exclusionsif { [in -key $ $Exclusions] } {forall E MachineExciude $Exclusions \f[strEQ $ $ && [in $sg $E.reject]}AssignServices $m $sgI} else {AssignServices $m $sgI}# AssignServices - describes the assignment of the services4t that are part of a service group, to a particular machine## Parameters:# m : Machine# sg : ServiceGroup (from table)## Individual services which compose a service group are listed in# attributes of the ServiceGroup, by type. For instance, there is# an attribute ‘printers’ whose value is the list of printer services# that are part of the group. The group is actually defined in atable,# where the value of an attribute like ‘printers’ is a list of keysof# records describing printer services.# For some service group requirements, the approach described above# does not work well, because the requirement is not a separatedservice# which could be independently assigned. For these cases, separate# tables describe the requirement, by service group name.prescription AssignServices {m sg} {# Subgroups of the ServiceGroup must be assigned125forall G ServiceGroup $sg.subgroups {}Assignlndividual $m $G# Printersforall P Printer $sg.printers {} {PrinterDef $m $P* Filesystemsforall F Filesystem $sg.filesystems {} {Guardedlmport $m $F* Logical Filesystemsforall F FilesystemGroup $sg.logicals {}ImportGroup $m $F# Symbolic Links associated with the service group must existglobal SLinksforall L ServiceLink $SLinks { [objEQ $L.service $sg] }SymLink $m $L.source $}# Arbitrary directories associated with the service group mustexistglobal Dirsforall D ServiceDir $Dirs { [objEQ $D.service $sgj } fdir $m $D.dir* File copies required for the service group must existglobal FileCopiesforall F ServiceFileCopy $FileCopies { [objEQ $F.service $sg] }FileCopy $m $ $F.source $F.dest}}* FileCopy- describes a file that is required to exist* on a machine, and to have the same contents as a file* of the same name in another directory on the machine.* Parameters:* m : Machine - machine on which file must exist* name : name of file* source : name of dir in which source file exists# dest : name of dir in which copy is required to existprescription FileCopy {m name source dest) {* Clearly the source file must exist126narrow { require S File $source/$name -closure $m.root U }# The directory for the copy must existglobal root daemondir $m $dest $root $daemon 0755# The copy file itself must existrequire S File $source/$name -closure $m.root {require D File $dest/$name -closure $m.rootlogical $D.contents eq $S.contentslogical $D.perms $S.permslogical $D.owner == $S.ownerlogical $ == $}}}# SymLink - describes a symbolic link that must exist# Parameters:# m : Machine on which link must exist# source : name to which link points# dest : name of linkprescription SymLink {m source dest} {require L SymLink $dest -closure $m.root {logical $L.ref s= $source}}# dir - describes a directory that must exist## Parameters:# m : Machine on which dir must exist# path : String pathname of directory# owner : Integer owner uid* group : Integer group gid* mode : Integer permission modeprescription dir {m path owner group mode} {require D Directory $path -closure $m.root {logical $D.owner == $ownerlogical $D.perms == $modelogical $ == $group}}# PrinterDef - describes a remote printer definition that* must be present on a machine* Parameters:127# m : Machine* pd : Printer (from table)*prescription PrinterDef {m pd} {global Allnarrow { or {require M Machine [val $] $All {}require M MachineProxy [val $] $All U}if { [strEQ $ $]# Printer should be locally defined on its server} else {* A PrinterEntry must existrequire P PrinterRecord [val $] $m.printcap {logical $ 5= $pd.namelogical $P.aliases 5= $pd.aliaseslogical $P.lp s=logical $P.rm s= $pd.serverlogical $P.rp s= $pd.nameif { [strEQ $pd.maxSize “1 } tlogical $ == 0} else {logical $ == $pd.maxSize}logical $ s= /usr/spool/print/[val $]logical $P.ty s= $pd.typelogical $P.note 5= $pd.note# The specified spool directory must existglobal root daernondir $m $ $daemon $daemon 02755}}44 ImportGroup - describes the importing of a group of# filesystems by an individual machine# Parameters:# m : Machine# fg : FilesystemGroup (from table)#prescription ImportGroup {m fg} {* Each part must be imported individually, if not explicitly# excepted for this machineglobal Exclusionsif { [in -key $m.narne $Exclusions] } {128forall E MachineExciude $Exclusions {[objEQ $E.machine $m]}if { [in $fg $E.noimportgroup]SafelmportGroup $m $fg}}} else {SafelmportGroup $m $fg}}## SafelmportGroup - describes the importing of a group# of filesystems by an individual machine from which# they are not excluded.## Parameters:# m : Machine# fg : FilesystemGroup (from table)prescription SafelmportGroup {m fg} {# Every filesystem in the group must be importedforall F Filesystem $ {}Guardedlmport $m $F}# Master root dir must exist if specifiedif { ! [isNIL $fg.root] }if { [strEQ $ $]}# This machine is server for the filesystem containing root# dirif { [val $fg.root.canonicalize] }* Server name space should be adjustedSymLink $m [val $fg.root.fs]/[val $fg.rootName] \$ fg. rootCname}} else {# This machine is a regular clientif { [strNE $fg.root.mountPoint “1 } {SymLink $m [val $fg.root.mountPoint]/[val $fg.rootName] \$ fg. rootCname} else {SymLink $m /nfs/[val $]/[val $fg.rootName] \$ fg. rootCname}}}}## Guardedlmport - describes import of a single filesystem129# on a single machine if not excluded.## Parameters:# m : Machine# f : Filesystem (from table)prescription Guardedlmport {m f} {global Exclusionsif { [in -key $ $Exclusions] } {forall E MachineExclude $Exclusions f [objEQ $E.machine $m]{if { ! [in $f $E.noimport]ImportSingle $m $f}}} else fImportSingle $m $f}# ImportSirigle - describes import of a single filesystem* on a single machine.# Parameters:# m : Machine# f : Filesystem (from table)#prescription ImportSingle {m f} {if { [strEQ $ $] } {# Importing is not done on server, but namespace adjustment* may beif f [val $f.canonicalize]ImportSupplemental $m $f $f.fs 1}} elseif f [strNE $f.mountPoint ‘“‘1 } {NFSlmport $m $f.tserver $f.fs $f.mountPoint $f.soft$f . quotaImportSupplemental $m $f $f.mountPoint 0} else {# Mounts below /nfsNFSlmport $m $f.@server $f.fs /nfs/[val $] $f.soft \\$f . quotaImportSupplemental $m $f /nfs/[val $] 0}}## ImportSupplemental - describes the state associated130# with import of a filesystem# Parameters:# m : Machine# f : Filesystem (from table)# mount : String name of mount point for filesystem# server : Integer - 1 if m is server, 0 otherwise## The supplemental state involves various symbolic links.prescription ImportSupplemental {m f mount server} {# Symlink for name space required# if cname is “, this link is not requiredif { [strNE $f.cnarne “1 && \$server II [strNE $f.cname $f.fs] )SymLink $m $mount $f.cname)# Other symbolic linksglobal FSLinksforall L FilesystemLink $FSLinks { [objEQ $L.fs $fjSymLink $m $mount/[val $L.source] $}# Architecture specific setup: the generic, bin, lib dirsglobal FSArchforall L FilesystemArch $FSArch { [objEQ $L.fs $f I } {# ArchDirs $m $mount $L}}## NFSlmport - describes import of a filesystem via NFS## Parameters:m : Machine# server : Machine that is server server# fs : String name of filesystem on server# mountPoint : String name of mount point# soft : Integer - 1 if soft mount required# quota : Integer - 1 if quotas must be enabled#prescription NFSlmport {m serverName fs mountPoint soft quota}global Allnarrow { logical {} {} [in -key $serverName $All] }# Mount point directory requiredglobal root wheeldir $m $mountPoint $root $wheel 0755# Handle possibility of alternate servers for particular subnets131global Alternatesif { [in -key [list [val $serverName] [val $m.subnetl] \$Alternates] }require A ServerAlternate \[list [val $serverName) [val $m.subnet]] $Alternates {fs $m $A.alternate $fs $mountPoint $soft $quota}} else {fs $m [val $serverName] $fs $mountPoint $soft $quota}# fs - describes a filesystem that must be defined on# a machine## Parameters:# m : Machine# server : String name of server# fs : String name of filesystem on server# mountPoint : String mount point# soft : Integer - 1 if soft mount required# quota : Integer - 1 if quotas must be enabled#prescription fs {m server fs mountPoint soft quota} {narrow t logical {} [in $server $m.aliases] }require F FileSysRecord [list $server $fsj $m.f stab {# Same regardless of hard or soft mount:logical $F.dir s= $mountPointlogical $F.type s= nfslogical $F.options contains rwlogical $F.options contains intr# Vary by mount type:if { $softlogical $F.options contains retry=2logical $F.options contains timeo=20} else tlogical $F.options contains bgIif {! $quota}logical $F.options contains noquota# ArchDirs - Describe symlinks that must exist for architecture# specific directories.132## Parameters:# m : Machine# root : String root of architecture specific dirs# a : FilesystemArch (from table)prescription ArchDirs {m root a} {set path $root/[val $a.source]forall D Directory -closure $m.root \[globEQ “$path” $D.fullPath]if f [in -key $m.arch $D.contents] } {# Architecture specific dirs are here: links areappropriateif { [val $a.subdirs] } {# Link specific subdirs below the arch-specific dirglobal root daemondir $m $ $root $daemon 0755SymLink $m [val $D.fullPath]/[val $m.archj/bin \[val $]/binSymLink $m [val $D.fullPath]/[val $m.arch]/lib \[val $]/libset path [val $m.arch]forall D2 Directory $D { [globEQ “$path” $D2.fullPathj }if [in —key obj $D2] } {SymLink $m [val $D.fullPath]/[val $m.arch]/obj \[val $]/obj}if { [in -key share $D] } tSymLink $m [val $D.fullPath]/share [val $]} else {SymLink $m [val $D.fullPath)/generic \[val $a. link] /generic}} else {# Link the arch-specific dir itselfSymLink $m $D.fullPath $}}133A..2 Sample Table EntriesHere are a few sample entries from the Printer table, as they appear in the fileprinter, table:hp3061hp3061{HP 4si (in CC306)} *c_hp4sj,CC3061Hp 4silRoom CC30611w1O61wl06gariba1di laserwriter fNEC Silentwriter (in CC106) 1} \*c_nec,CC1O6INEC SilentWriterlRoom 1061cicsrlwllwcicsrllp lwc default {Silentwriter (in CC289)} \*c_nec,cc2891 1110000lw238llw238lclinker clink *c_nec,CC2381NEC SilentWriterlDraft Room\3121In this case, backslash characters are inserted to indicate where a single line of the file hasbeen broken for presentation. The backslashes do not actually appear in the file.


Citation Scheme:


Citations by CSL (citeproc-js)

Usage Statistics



Customize your widget with the following options, then copy and paste the code below into the HTML of your page to embed this item in your website.
                            <div id="ubcOpenCollectionsWidgetDisplay">
                            <script id="ubcOpenCollectionsWidget"
                            async >
IIIF logo Our image viewer uses the IIIF 2.0 standard. To load this item in other compatible viewers, use this url:


Related Items