r2 - 24 May 2006 - 23:29:08 - PeterNicYou are here: Wiki >  AppLogic24 Web > AdvADLSpec
ALERT! AppLogic 2.4 Documentation The latest production release is AppLogic 3.0.30

ADL - Application Descriptor Language

Overview

ADL is a language for describing applications within the AppLogic application model, where applications are built out of multiple components, with each component being an instance of a virtual appliance, with its own OS and application software. In the interpretation of ADL, "host" and "hardware" (or any type of resource) do not necessarily correspond to physical resources, they may be virtual devices that share the same hardware.

ADL is based on UDL - a generic language for describing hierarchically structured data in plain ASCII text form. You can find the description of UDL in a separate document, however understanding UDL in general is not necessary - this document contains a complete description of the ADL syntax.

Descriptor Types

These are the descriptor types defined in ADL:

component describes a simple component, which is running on a single host. Typically a component is a single "network appliance" that performs one specific service, e.g., an HTTP server, a database server, etc. Component descriptors are either written manually by a developer or produced by a GUI tool.
assembly describes a composite component, consisting of several interconnected components (either simple components or other assemblies). An assembly descriptor is also used to describe the structure of an entire application. Assembly descriptors are either written manually by a developer or produced by a GUI tool.
package package descriptors are used as "table of contents" for an application, a catalog (catalogs are sets of re-useable components that can be shared among applications), or for data caches used internally by the AppLogic software. The package descriptors contain configuration information and a list of component and assembly descriptors. They can also include binding information linking the abstract descriptors to installed boot volume images for the components.

Syntax Rules That Apply to All Descriptor Types

As ADL is based on UDL, all of its descriptor files share common syntax properties, as follows:

Lexemes

Here are the smallest units of grammar used in the ADL language, defined as Perl-style regular expressions:

Reg expr Sym Use Notes
[A-Za-z_][A-Za-z0-9_]*   SIDENT entity name, entity type A simple identifier. This is the identifier sub-set that is acceptable to most text-based languages used, including shell command interpreters (bash, csh), Perl,C, Java, etc. Most user-defined names in the ADL language are of this type (exceptions are noted, where needed).
[A-Za-z_$.-]  [A-Za-z0-9_$.-]*   IDENT entity name, attribute name An identifier. Similar to a C identifier, but '-', '$' and '.' are also valid characters.
[^,"'>=#\s]+   STR attribute value A "bare" string. A string that is not quoted is allowed as a value for an attribute, if it does not contain any special characters.
'[^']*' or
"(\\["]!\\t! \\n!\\r![^"])*"
STR attribute value A quoted string, with two variants - single-quoted and double-quoted, interpreted in a manner similar to Perl - the single-quoted string recognizes no special meta-characters and can quote any printable characters except a single quote; the double-quoted string recognizes the \ meta-character and allows quoting of the double-quote itself and some non-printable characters as well.
[\]\[{}:,='"]   punctuation See the Punctuation Details section below.
=>   punctuation Association separator
[ ]+   whitespace whitespace is a syntax separator, whenever two adjacent lexemes cannot be distinguished otherwise (e.g., two identifiers). In all other cases, whitespace between lexemes is simply ignored.
\n   separator A newline or the EOF assertion. Multiple newlines are treated as one.

Punctuation Details

ADL is line-oriented, that is, it treats the newline character differently from other whitespace. Please note that in all the syntax descriptions below, the newlines are significant and the presence of a newline in a syntax example means that it is required.

Here is the meaning of other punctuation characters in ADL:

:   separates an entity definition from an in-line list of attributes for that entity
,   separates attributes in an attribute list following an entity definition (in-line attributes)
{}   block separators. These must appear alone on a line. A pair of braces encloses a set of attributes and/or sub-entities related to the entity after which they appear. Only one block is allowed per entity and only a single pair of braces should be used to enclose it, i.e., constructs like these below are invalid:
input X
   {
   { # double brace - illegal
      protocol=http
   }
   }

input X
   {
   }
    { # second block for same entity - illegal
   protocol=http
   }
[]   array block separators. A pair of square brackets following an entity heading identifies it as an "array" entity. Like the { } separators, these must appear alone on a line. Each line in the [ ] block is a comma-separated list of attributes for a single array element.
\   when found at the end of a line, this is a 'line continuation' character. The next line is treated as part of the current line.
#   comment separator. All characters following #, up to the end of line are ignored (including the \ line continuation character).

Descriptor Structure

Each descriptor file has the following overall structure:

entity-type entity-name
   {
   
attributes-and-subentities
   }

Where:

entity-type is one of component, assembly or package and identifies the type of descriptor that is contained in the file.

entity-name is the name of the entity being described in this file (SIDENT).

attributes-and-subentities is an unordered set which contains any number of attributes and sub-entities. Each attribute is on a single line and has the form: 'name=value'., where name is an identifier (IDENT) and value is a string value (STR). Each sub-entity has one of the following forms:


name : attributes

typename :attributes

name
   {
   
attributes-and-subentities
   }


typename
   {
   
attributes-and-subentities
   }


type and name are the type and the name of the sub-entity, respectively.

attributes is a comma-separated list of name=value pairs. Note that attributes can also be specified in the { } block following the entity heading line. When attributes are specified on the same line as the entity definition (after the colon), binary attributes can be specified without a value (just the attribute name, meaning 'set to 1'), e.g.

   volume boot: dev=/dev/hda1, ro

is the same as

   volume boot: dev=/dev/hda1, ro=1

Each subentity type defines a namespace, and within that namespace only one subentity of a given name can exist. That applies to the sub-entities with no type at all (one can think of the subentities with no type as having the empty string as the type).

Specifying attributes both in-line and in the { } block is allowed, it should be avoided except in the cases where one particular attribute should stand out (e.g., the .class attribute in a subordinate component's specificaion); otherwise for simpler sub-entities with few attributes the inline syntax is preferred; for more complex entities that have many attributes and/or sub-entities, use the { } block.

Component Descriptor Syntax

The component descriptor contains one component entity, defining either a "singleton" component or an instantiable class of components. There is no difference between the definition of a singleton and a class, except that instantiable classes are required to reside in a library of components referred to as a 'catalog'. Also, either type of component can be used in an assembly, but a singleton can appear only once in the structure of an application, while an instantiable component can be used multiple times.

Below are two examples of the component descriptor structure; the first example is the current standard form, the second example shows the old format of the boot information specification. The old format is fully supported for compatibility with existing catalog appliances.

component name
   {
   volume sname : dev= pathname [, mount= pathname][, ro] [, high_bw]

   resource cpu : min= val , max= val
   resource mem : min= val , max= val , abs= val
   resource bw  : min= val , max= val

   (input|output)  sname : protocol= name [, mandatory ][, alias = dnsname ]
   interface  sname

   property  sname  : type=(string|integer|ip_addr) [, filter= regexp ] \
                    [,min= val ,max= val ] [, (mandatory| dflt= val) ]
   property  sname  : type=(string|integer) [, values= v1|v2|v3... ] \
                    [, (mandatory| dflt= val ) ]
   .config_mode=(dhcp|volfix)
   virtualization: mode=(paravirt|hvm)
      {
      path = filename
      initrd = filename
      options = " string "
      console = " string "
      device_schema = " string "
      }

   visual
      {
      ...
      }
   }

component name
   {
   volume sname : dev= pathname, [, ro] [, high_bw]

   resource cpu : min= val , max= val
   resource mem : min= val , max= val , abs= val
   resource bw  : min= val , max= val

   (input|output)  sname : protocol= name = [, mandatory][, alias = dnsname =]
   interface  sname

   property  sname  : type=(string|integer|ip_addr) [, filter= regexp ] \
                    [,min= val ,max= val ] [, (mandatory| dflt= val) ]
   property  sname  : type=(string|integer) [, values= v1|v2|v3... ] \
                    [, (mandatory| dflt= val ) ]
   cfgfiles
      [
      vol= sname , path= filename
      vol= sname , path= filename
      ...
      ]

   kernel: path= filename  [, initrd = filename ] [, options = " string" ]

   visual
      {
      ...
      }
   }

The component entity has the following attributes defined:

.migrateable If set, it allows the component to be moved from one CPU to another (provided that the component is running in a virtual machine and there is VM migration support). There is no need to specify this attribute in a component - the default, if not specified, is 1 (TRUE). This is a boolean attribute (valid values: 0,no,false,1,yes,true; also may be specified inline without value at all, meaning '1').
In the absence of this attribute, .migrateable=1 is assumed by default. Note that this is unlike most other boolean attributes defined in ADL - they usually default to 0.
.server If .migrateable is set to 0, defines the name of the server on which this component is to run. This attribute, along with the .migrateable attribute are usually set from an outer assembly, not in the component descriptor itself. The compiler will output a warning if this attribute is set in the component.
.standby If set, this means the component is not started automatically when the application is started. The .standby attribute is not meant to be set in a component descriptor directly. Normally, it is set from an assembly that contains the component or re-directed to the top-level assembly of an application to allow enabling/disabling parts of the application by modifying the application's properties (stored in the top assembly - see the Package Descriptor further on). This is a boolean attribute.
.boot_tout boot timeout, in seconds. If specified and set to a non-zero value, indicates the amount of time the application controller is to wait for the component to become active before assuming that it has failed to start. If this attribute is omitted or is set to zero, a default value that is configured for the AppLogic controller is used.
.os_type obsolete this attribute should not be used in newly created descriptors. See the virtualization entity description instead. .os_type specifies the OS that this component uses. This information is necessary for support of multiple OS types running in virtual machines. The value provided is not interpreted by the ADL build system; together with the data in 'kernel' entity described below it is intended to be passed along to the VM boot loader. If not specified, 'linux' is assumed.
.config_mode specifies how the component should be configured. The allowed values are: dhcp and volfix. The default is dhcp. This attribute should be used explicitly only for backward compatibility, if the volfix functionality should be retained for a given component. This attribute is ignored and the mode is set to volfix if the descriptor does not have the virtualization entity. This is to allow old descriptors (which belong to components that rely on volfix and do not support the dhcp configuration) to work without modification.
.field_opt a bitmask of options for enabling various debugging and troubleshooting support. Note that this attribute does not follow the normal rules for overriding property values from an assembly, which apply to all other pre-defined attributes - the .field_opt value specified for a component is kept as "class field options", while any setting of the same attribute for an instance of the component in an assembly is kept as "instance field options".
.category an arbitrary string that defines the general category to which the component belongs. It is allowed by the ADL syntax, but is not interpreted in any way. It is intended for use by the AppLogic visual tools to organize components in component libraries (catalogs).
.description a short description of the component. Similarly to .category , the value of this attribute is arbitrary and intended for documentation purposes only.

All component attributes are optional and need not be present in the descriptor.

All of the attributes are also valid properties of the component, which can be overridden in an assembly that contains the component. Note that the attribute names are prefixed with a dot, to avoid name conflicts with regular properties (see the 'property' entity below).

The table below is a summary of the valid sub-entities in a component, followed by sections that explain each sub-entity in detail.

volume defines a volume that contains a file system used by the component. At least one volume entity must appear in each component.
resource defines the requirements of the component towards the hardware resources that must be made available for it to run.
input, output these entities define "terminals" of the component, which are network interfaces intended for connection with other components in the same application.
interface used to enable and configure network interfaces that are not meant for connecting to other components (as the input and output terminals are)
property defines a configurable property of the component.
cfgfiles defines a list of configuration files that need to be checked for property markup and updated accordingly.
kernel obsolete - use virtualization instead. This entity contains OS-specific boot information, its contents depend on the value of the .os_type attribute of the component.
virtualization This entity defines the virtual environment for which the component is designed and contains boot-specific options to be provided to the component's boot loader.
visual Visual presentation data. ADL does not define the contents of this entity. It is intended for a GUI editor to store information related to how the component is displayed in the editor's window (color, icon shape, layout of terminals, etc.).
The contents of this entity must conform to the general syntax rules of UDL, which were presented earlier in this document, in the Syntax Rules that Apply to All Descriptor Types section. Also, see the UDL specification for more details.

volume

defines a volume that contains a file system used by the component. At least one volume entity must appear in each component. The volume entity has the following attributes:

dev= the device name, as it is seen by the host OS of the component. The physical device containing the filesystem (and which can be either local or remote) will be made available to the host OS under that name. This attribute must be specified for all volumes. No two volumes in the same component can have the same value for this attribute.
mount= optional mount path for the volume. This attribute can be specified for volumes that are not mounted automatically by the component's operating system. Specifying this attribute for system-mounted volumes (e.g., the boot volume) has no effect, as the OS will mount those volumes before it receives any configuration from AppLogic. The software resident on the component will receive the mount path for each volume as part of its configuration and is responsible for mounting the volume appropriately. An AppLogic component is not required to support this. Note that the meaning of "mount path" may vary between OS types and is not necessarily supported by every OS.
class If specified for an instantiable component that resides in a catalog, this attribute specifies that the volume
data is common to this class of components and an image of the volume is present in the catalog. See also the 'type=' attribute below. If specified for a singleton component, the volume data is to become a common template image whenever the singleton component is converted to an instantiable component.
If the 'class' attribute is not present, there is no common image for the volume and the name of an image for the volume must be configured for each instance of the component (this is usually done in the assembly that contains the component).
type= This attribute is mandatory for volumes that have the 'class' attribute set. It speficies how the common class image of the volume is to be provided to each instance of the class. It can have the following values:
instantiable - the 'class' image is the initial data for each instance and a separate copy of it is provided to each instance. (It is assumed that each instance's actual data will not differ significantly form the initial image and that the 'copy' may be replaced by a logical equivalent thereof, i.e., only the modified portions of the data may be kept separately for the instance, using the common image for the unmodified data).
template - This is similar to the 'instantiable' type, but a complete copy of the volume is made for each instance. This is useful for database templates.
common - the 'class' image is accessed directly by each instance of the component. Volumes of this type cannot have configuration files that are writable by the ADL build system stored on them - i.e., entries in the cfgfiles table (described further on) for these volumes are invalid. The 'common' type also implicitly sets the 'ro' and 'shared' attributes (see below).
blank - there is no image provided, each instance is to receive an empty un-initialized volume upon boot. 'null' is intended for specifying swap volumes. It also requires that the 'size=' attribute be specified.
size= Volume size, for volumes of type blank . This must be a non-zero integer value, specifying the size in bytes. K, M and G suffixes can be used, meaning Kbytes, Mbytes, etc.
mandatory this applies only to volumes that do not have the class attribute and indicates that the volume is required for the operation of the component. If mandatory is not set, the component must be prepared to work correctly even if the device (which is seen by the component's software as specified by the dev= attribute) is not present.
ro means the filesystem on the volume is not written to by the component. Specifying this attribute does not guarantee that the component itself will not attempt to write to the volume. However, the presense of this attribute may be used to prevent write operations from going through. Specifying 'ro' also implies 'shared' - see below.
shared this attribute, if present, means that the volume image can be shared among multiple instances of the same component, as well as with other components.This is mostly useful if the 'ro' attribute is also specified, or if the filesystem on the volume has a built-in mechanism for read/write sharing at block level. Note that 'shared' need not be specified for class volumes of type 'common' (see type= above).
boot marks the volume as an OS boot volume. Note that the file paths specified in the 'kernel' sub-entity are relative to the root directory of the boot volume. Exactly one volume in a component must have the boot attribute.
high_bw identifies a volume that is accessed frequently and/or large amounts of data are transferred to/from it. This is a hint used for resource allocation, making it preferable to use a local resource for this filesystem.
local_only if specified, this attribute means that the volume must reside on the same host as the component instance that uses it.

A 'volume' entity that has no 'class' attribute also defines a configurable property on the boundary of the component, which can be set the same way as other properties of the component - see the property entity below. The mandatory attribute for such volumes works the same way as the mandatory attribute for properties. A 'volume' property should be set to the logical name of one of the application's volumes (as found in the application's package descriptor). Note that this means volumes and properties share namespace and one cannot define a volume and a property of the same name.

resource

The resource entities define the requirements of the component towards the hardware resources that must be made available for it to run. The name of a resource entitiy must be one of: cpu, mem or bw. The definition of these entities is as follows:

cpu The min and max attributes of this sub-entity define the CPU time needed by the component, relative to the CPU time of other components that are allocated on the same physical CPU expressed as a decimal fraction or as percentage value. The value may exceed 1 (or 100%), if the component requires 2 or more CPUs on an SMP system.
mem defines the amount of memory needed by the component; The three attributes of 'mem' are interpreted as follows:
max - the maximum amount that should be allocated to the component (i.e., it will not benefit its operation if it had more memory),
min - the minimum amount that should be allocated for the component to retain near-optimum functionality,
abs - the minimum amount of memory necessary for the component, under which it will cease to be operational.
The number may be suffixed by a scale modifier like K and M and G, with their usual meaning of Kbyte (1024), Mbyte (1048576), etc.
bw defines the minimum and maximum network bandwidth necessary for the component to operate, expressed in bits/sec (scale modifiers like K and M and G are allowed; unlike the memory units, these modifiers follow the networking tradition - they mean decimal orders of magnitude K=1000, M=1,000,000, etc., e.g., 1000M means 1 gigabit/s, same as 1G).

The 'resource' entities are mandatory , all must be specified in a component's description and all must have the 'min' and the 'max' value specified. The 'abs' value may be omitted and is assumed to be equal to 'min' by default.

input, output

These entities define "terminals" of the component, which are network interfaces intended for connection with other components in the same application. A "terminal" is a special kind of network interface - it is used only for one specific protocol and only in one direction ("direction" here refers to flow of control, not of data - i.e., an output terminal is an interface used by a protocol client; while an input terminal is for a server). The presence of a terminal entity automatically defines a host name that resolves to the remote side of the connection in which this terminal participates. The terminal entities have the following attributes:

protocol this is the name of the network protocol filter for this terminal. The protocol name corresponds either to a pre-defined protocol (e.g., http, nfs, etc.) or to a custom protocol that has filtering rules defined in the application's package descriptor. This attribute must be present for each input or output. If no protocol control is needed for the terminal, use 'protocol=any'.
mandatory if present, this binary attribute means that the terminal may not be left unconnected. Mandatory terminals will trigger a compilation error in an assembly that includes a component with such a terminal left unconnected.
gateway (for outputs only) - if present, identifies the terminal as the default gateway for the component. A gateway output, instead of being programmed for connection to a single input on the remote side, is configured as the interface through which all connections outside the local network should go. When it is connected in an assembly, the remote end of the connection becomes the default gateway in the IP routing table and it is also programmed as the DNS server. Usually, a gateway terminal would be connected to a NAT router with DNS forwarding (and/or cache) or something similar.
alias Output terminals can also have an alias attribute, defining an additional host name under which the remote side of the connection is known (in addition to the terminal name itself, which is always added to the 'hosts' file).

interface

This entity type is used with one of two fixed names - 'external' and 'default'. It is used to enable and configure network interfaces that are not meant for connecting to other components (as the terminals are - see above) and have no restrictions on the type of connections that can be made. The syntax for the interface entities is as follows:

    interface external
    interface default

The 'interface external' entry enables the device named 'eth0' to be used as the external network interface of the component (accessible from outside the application). If enabled, eth0 is not used for terminals and its IP configuration is not set up automatically. Instead, it is expected that properties are defined to configure the network adapter.

The 'interface default' entry enables configuring an unused network interface for unrestricted use, with an automatically assigned IP address on the same subnet as the ones used for terminal connections. The assigned IP address is made available to the AppLogic controller as the IP address of the component; this can be used for maintenance logins.

property

The property entity defines a configurable property of the component. Any parameter that may need to be configured can be defined as a property. The values of properties are made available to the component's software in the following ways:

  • all properties are available for access by shell scripts and executables as environment variables defined in a shell file that is stored automatically on the component's boot volume and can be included by any script;
  • also, any files named in a 'cfgfiles' entity (see below) are searched for special markup identifying a portion of the file as corresponding to a property value - all matching instances are automatically updated to reflect the property value as configured in the component's descriptor or as overridden by any assembly in which the component participates. There are several variants of "markup", which allow making it appear as comments to the software that uses the file, so it is completely transparent to the component's code. See the Property Markup Syntax section later in this document.

Note that since a volume can appear as a configurable property on the boundary, volumes and properties share namespace and one cannot define both a volume and a property of the same name.

The property entity has the following attributes:

type= defines the propety type, the value of this attribute must be one of: string, integer or ip_addr. If the 'type=' attribute is not specified, 'string' is assumed.
filter= A regular expression defining the set of valid values for the property. The expression must be coded in the syntax defined by Perl for regular expression pattern matching. The match is done on the entire property value - that is as if /^expression$/ was used in a Perl statement to check for a match (where expression is the value of the filter attribute.
This attribute is optional. If not present, the value ".*" is assumed (match any string).
values= This attribute can be used as an alternative to the filter= attribute. It is treated exactly as the filter attribute by the ADL compiler, except that the use of values= expr instead of filter= expr is a hint to the GUI editor that the regular expression is a simple concatenation of strings to be matched, in the normal regular expression form "string1!string2!..." etc. This can be used to display a drop-down list of values in a property sheet instead of a free-text edit box.
min=
max=
Mininum and maximum values for an integer property. If the specified property type is 'integer', these optional attributes specify the limits of valid values. They are applied in addition to any regular expression pattern specified by the filter= attribute.
The presence of a '-' or '+' sign in one of these values is taken to mean that the integer comparison against the limits is to be done as for signed integers.
mandatory If present, this attribute indicates a property with no default value. When the component is used in an assembly, a value for the property must be supplied in the assembly or it must be redirected to the assembly boundary; in the latter case, the corresponding property of the assembly also takes on the 'mandatory' attribute.
If 'mandatory' is not specified, a default value for the property should be given with a 'dflt=' attribute (see below).
dflt= specifies a default value for the property. This attribute cannot be used together with 'mandatory'.
lowercase indicates that the property value is to be converted to lowercase before it is used to configure the component. This should be used for properties that need to appear as case-insensitive to the user, but provide the component a consistent value that can be compared using case-sensitive compare. Note that the lowercase conversion is done in the C locale.

cfgfiles

defines the configuration files that need to be checked for property markup and updated accordingly. This entity is an array, each entry defines one configuration file and has these attributes:

vol - names the volume on which the file is located (this should match one of the component's volumes, as defined by the volume entities). A value for this attribute must be specified for each cfgfiles array element.

path - this is the file name of the configuration file, relative to the volume on which it is located. Note that this may be different from the path where the application "sees" that file - depending on how the particular volume is mounted by the component. A value for this attribute must be specified for each cfgfiles array element.

quoting - defines the method for quoting meta-characters in the configuration file. A "meta-character" is any character that has a special meaning in the config file and must be quoted (or "escaped") in some manner in order to appear as a data character and not in its special-function role. The 'quoting' attribute can be set to one of the following strings:


      conf - no quoting (default).
bash - data values that are enclosed by quotes are assumed to use \" to mean the quote character and \\ to mean the backslash. Backslashes that don't quote a " or \ character are left untouched, i.e., if the user sets a property value to "abc\def"ghi\n", the result written into the config file is "abc\\def\"ghi\n". Values that are not surrounded by quotes are limited to alphanumeric characters (an error is reported if such a property is set to a value with other characters, even if the filter for that property allows it).
perl, c - same as 'bash'
html - the characters that have significance in the HTML syntax (< > " and &) are encoded as &lt; &gt; &quot and &amp;, e.g., abc&def<ghi becomes abc&amp;def&lt;ghi in the config file.

NOTE: the cfgfiles sub-entity is useful only when .config_mode is set to volfix. In the dhcp mode, the component's boot volume will not be modified and it is expected to configure itself dynamically over the network.

virtualization

This entity contains the boot information needed to start the component in the virtual environment for which it is designed. The virtualization entity supersedes the kernel/os_info definitions and should be used instead of them. The presence of this entity also indicates a 'new-style' component descriptor and turns off the compatibility mode, which includes forced .config_mode=volfix.

The following attributes are defined for the virtualization entity:

mode= string defines the component's virtual environment. Valid values are paravirt (for components that have a para-virtualized kernel supported by the host system) and hvm (for components designed to run directly on hardware and require hardware-assisted virtualization if ran in a virtual machine).
options= "string" arguments to pass to the bootloader.
If mode=hvm, the string is interpreted as a space-separated list of 'name=value' pairs, which are passed to the virtual hardware emulator. Examples of parameters supported by the qemu emulator (used in XEN) include: acpi=(0!1), apic=(0!1), pae=(0!1), etc.
If mode=paravirt, the string is passed to the component's kernel command line, and may be available to the code running in the component's virtual environment, if the component's OS kernel supports that.
path= filename or
kernel_path= filename
the name of the kernel image file, relative to the boot volume's root directory. This attribute is meaningful only if mode=paravirt and is ignored otherwise. If path is not set, it is assumed that the component has the GRUB bootloader installed and its configuration file contains the correct location of the kernel image and the initial ramdisk, if one is used.
initrd= filename the name of the ramdisk filesystem image to use during boot. This attribute is meaningful only if mode=paravirt and is ignored otherwise. initrd is ignored if path is not set (in this case the names of both files are looked up in the GRUB configuration file found on the component's boot volume).
console= string OS System console configuration parameters. The format of this string is not part of ADL, the currently supported console parameters are defined in RefEditorClassEditorSimple
device_schema= string This is used to store the disk device naming convention, as used by the component's OS. The format of this string is not part of ADL: the device_schema attribute is reserved for use by the AppLogic application editor. See RefEditorClassEditorSimple for details.

kernel, os_info

obsolete, use virtualization instead. The presence of a kernel or os_info sub-entity in the descriptor indicates an old descriptor and the volfix configuration mode is forced automatically.

This entity contains OS-specific boot information, its contents depend on the value of the .os_type attribute of the component. The keywords kernel and os_info are equivalent, kernel is retained for backward compatibility.

When .os_type=linux , the following attributes are defined for the os_info entity:

path= filename - the name of the kernel image file, relative to the boot volume's root directory.

initrd= filename - the name of the ramdisk filesystem image to use during boot. The kernel image file and the ramdisk image file are typically produced as a result of building the Linux kernel.

options= "string" - other arguments to pass to the bootloader's 'kernel' command line.

When .os_type=legacy, the following attributes are defined:

options=" name=value name=value ... "

The legacy OS type is used for all hardware-assisted virtual machines. The name=value pairs are not interpreted, they are passed on to the HVM emulator directly. Examples of parameters supported by the qemu emulator (used in XEN) include: acpi=(0!1), apic=(0!1), pae=(0!1), etc.

Assembly Descriptor Syntax

The assembly descriptor contains one assembly entity, defining a new component that consists of several components, which can be either simple components or other assemblies. An assembly that is made up entirely of instantiable components (all residing in a catalog), is itself considered instantiable. If a singleton component appears anywhere in an assembly, the assembly itself is a singleton and cannot be moved into a catalog.

The assembly descriptor has the following structure:

assembly sname
   {
   .category = text
   .description = " text "
   .console = " subord-name "

   input  sname
   output  sname
   ...

   property  sname &nbsp[ : dflt = value ]
   property  sname &nbsp[ : mandatory ]
   ...
   volume sname

   subordinate  sname
      {
       .class = clsname
        attr = val
       ...
      }

   connections
      [
       sub-name . trm-name => sub-name . trm-name
      ....
      ]
   visual
      {
      ...
      }
   }

The following attributes are defined for assemblies only, they have no meaning in simple components:

.console the name of a subordinate component, which will serve as the default login target for this assembly. This makes it possible to define an assembly that behaves like a simple component in the sense of allowing the assembly to accept a login request the same way as a simple component that has support for a login console can. As not every component is required to have a login console (depends on the OS and the software installed on it), an assembly is not required to have one. If the assembly does not need a login console or does not have any component that can serve as one, this attribute can be omitted or set to the empty string. Note that as a special exception, when the attribute is omitted (rather than set explicitly to the empty string), and the assembly has only one subordinate it is silently assumed that this subordinate is the default login target. The subordinate specified by the .console attribute (or assumed by default, for single-subordinate assemblies) can itself be an assembly.
NOTE: it is not an error to specify a subordinate that does not support console login (either because it is a component that has no console, or because it is an assembly that has .console set to emtpy): the only outcome of such a setting will be that the resulting assembly will not support console login.

The following attributes are defined for an assembly; they have the same meaning as their counterparts for a simple component:

.category an arbitrary string that defines the general category to which the component belongs. It is allowed by the ADL syntax, but is not interpreted in any way. It is intended for use by the AppLogic visual tools to organize components in component libraries (catalogs).
.description a short description of the component. Similarly to .category , the value of this attribute is arbitrary and intended for documentation purposes only.

The order of entities in the assembly is not important and all of the sub-entities are optional, except that an assembly must have at least one subordinate entity.

Here is a summary of the sub-entities of the 'assembly' entity, followed by sub-sections defining each one in detail:

input, output these sub-entities define the assembly's terminals.

property defines a property of the assembly. Each property must be connected to at least one property of a subordinate component - see the 'subordinate' entity.
volume defines a property of the assembly, similar to the 'property' entity.
subordinate defines a subordinate component in the assembly.
connections defines the assembly's connection table. This is an array entity, each element corresponds to one connection.
visual Visual presentation data. ADL does not define the contents of this entity. It is intended for a GUI editor to store information related to how the assembly is displayed in the editor's window (color, icon shape, layout of terminals, layout of subordinate components, routing of connections, etc.).
The contents of this entity must conform to the general syntax rules of UDL, which were presented earlier in this document - in the Syntax Rules that Apply to All Descriptor Types section. Also, see the UDL specification for more details.

input, output

These sub-entities define the assembly's terminals.

The terminal entities support a single attribute: mandatory . Specifying this attribute means that the terminal must be connected; mandatory terminals will trigger a compilation error in an assembly that includes a component with such a terminal left unconnected. Note that specifying the mandatory attribute for an assembly is not necessary if the subordinate component's terminal to which it is connected is already mandatory.

An assembly can have any number of terminals, except for the top-level assembly of an application, which should have no terminals.

property

The property entity defines a property of the assembly. Each property must be connected to at least one property of a subordinate component - see the 'subordinate' entities below. A property may have a default value, idenitified by the dflt attribute. The default, if specified, overrides the default value in the subordinate components to which the property is connected. Alternatively, ' mandatory ' may be specified, requiring that the property be set from outside (e.g., in an outer assembly) even if the subordinate components to which it is connected have a default value for the property.

volume

This entity efines a property of the assembly, similar to the property entity. The property defined with the 'volume' entity must be connected to at least one 'volume' property on a subordinate component - see the subordinate entities below. The property defined by a volume entity may have the mandatory attribute specified, requiring it to be set, even if the components' volumes to which it is connected do not have the mandatory attribute set. Unlike regular properties, default= cannot be specified for a volume.

subordinate

The subordinate entity defines a subordinate component in the assembly. Each subordinate can have any number of attributes, each corresponding to a property (including 'volume' properties) of the component that is overridden with the specified value. In addition, the following pre-defined attributes with a special meaning exist for each subordinate, all having a name that begins with a '.' to distinguish them from regular properties:

.class specifies the class name of the subordinate component; this can be either the name of an instantiable class or the name of a singleton. This attribute is mandatory and cannot be omitted.
The class name is specified either as a simple name or in the form catalog-name.class-name, where catalog-name is the name of a catalog (either a catalog that belongs to the application or a global catalog configured in the AppLogic configuration file). The catalogs specified in the application package are looked up first.
When no catalog name is given, the class-name is taken to be that of a component class residing in the same place as the assembly - e.g., if the assembly is a catalog part, the subordinate is looked up in the same catalog; if the assembly belongs to an application the subordinate is looked up in the application's package.
.start_order defines the order of starting this subordinate, relative to the other subordinates in the same assembly. Lower numbers are started first and those with a higher number are not started until all those with lower numbers have started successfully. Subordinates having the same start_order number can be started in any order and may have their startups overlap in time. The start order is local to the assembly and the same start order numbers can be reused in different assemblies (the relative order of starting subordiantes in different assemblies depends on the start order numbers assigned to those assemblies). Subordinates with no .start_order attribute are started after all subordinates that do have the attribute.
.failover defines a failover group identifier. Components that have the same failover group ID in the application constitute a group of components that serve as backup for one another and therefore should never be scheduled on the same physical device (so that in case of hardware failure, some of them remain alive). The failover group ID is global to the application, that is, components with the same group ID in different assemblies are considered to belong to the same group. Setting this attribute to the empty string is allowed and is treated as if the attribute is not set at all (i.e., no scheduling preference for this component).
.ignore A boolean attribute. If it is set to 1 (true), specifies that the subordinate's operation is not critical to the assembly and if the subordinate fails to start, the application startup should proceed as normal. Note that this attribute cannot be redirected to the assembly boundary.
When setting this attribute, check that the other subordinates that have outputs connected to the one with .ignore set will work correctly if their outputs are unconnected.
.field_opt This sets the 'instance field-option' value of the subordinate. Unlike the other pre-defined attributes of a component (.migrateable, .boot_tout, etc.) which can be overridden by specifying the attribute of the same name in a subordinate entity in an assemlby, the component's own .field_opt is not overridden - it is kept as the 'class field-option' instead. See the .field_opt definition in the component descriptor syntax and also above where the assembly's attributes are explained.

All attribute names other than the pre-defined ones are considered to be property names of the subordinate component that need to be set to the specified value - this includes the predefined attributes of the subordinate component ( .boot_tout, .migrateable, .server, .standby ), as well as the component-specific properties defined in it by the 'property' or the 'volume' entities (see the component descriptor syntax).

A special type of value is defined indicating that the property is connected to the assembly's boundary: $.name, where name is the name of one of the 'property' or 'volume' entities in the assembly. If a property has to be set to a literal value that begins with the "$." characters, the value must be quoted to ensure that it is not interpreted as a property connection. More than one subordinate property can be connected to the same boundary property and all such properties get the default value from the boundary property definition if none is provided in an outer-scope assembly. The $.name can be used for the pre-defined attributes of the subordinate as well, making them regular properties on the assembly boundary.

The 'subordinate' entity in an assembly also accepts the resource sub-entities mem , cpu and bw , with the same attributes as defined in the Component Descriptor Syntax section.When applied to a subordinate that is a simple component, they override the resource settings in that component. The "override" must remain within the limits of the range defined in the component (i.e., the new range must no wider than the old one and must fit entirely into the old one). When applied to a subordinate that is an assembly, the specified resources are distributed pro-rata according to the relative weight of the resource requirements in each of that assembly's subordinates. If a resource setting for a subordinate assembly causes a component to receive a resource setting that is outside of the min-max range defined for it, an error is reported by the ADL linker.

connections

This defines the assembly's connection table. The connections entity is an array entity and each array element is an "association" in the form x => y, where x and y identify two terminals to be connected, each terminal identifier consists of a subordinate name and a terminal name separated by a '.' character. Terminals that are to be exposed as terminals of the assembly itself ("exterior" connections) are also defined in in the same table, with the following syntax:

$. atrm-name => sub-name . strm-name, or

sub-name . strm-name => $. atrm-name.

Both syntax variants are equivalent and mean that the terminal strm-name of subordinate sub-name is to be visible as atrm-name on the assembly (atrm-name must correspond to an input or output entity defined in the assembly). Since an input terminal is a 'network server' and an output terminal is a client, the following rules apply:

  • an output can be connected to at most one input
  • an input can be connected to any number of outputs (subject only to limitations on the number of clients that the component supports for the specific service)
  • an input terminal on the assembly boundary must be redirected to exactly one input of a subordinate compoent
  • any number of subordinate component's outputs can be redirected to a single output on the assembly boundary

Package Descriptor Syntax

The package descriptor is a "table of contents" file that defines the contents of an application or of a component library (a catalog). The package descriptor also contains references to volume images that are outside the application's root directory (the application is installed on the grid controller, while the volumes may reside on any of the grid's servers). For applications, it also contains the configuration settingscomponent of the application.

Following are the different types of package descriptors:

application ToC for an entire application, contains the app's configuration data and references to other package descriptors
catalog ToC for a catalog (library of components), contains a list of components
recycle, clipboard ToC for work directories used by the GUI tools. They have a format similar to the 'catalog' package descriptor.

The package descriptor contains one entity of type 'package'.

An application package descriptor may also contain an entity of type 'assembly', with the same structure as the one found in an assembly descriptor, except that it cannot have terminals and properties on the boundary. It is used as the topmost component of the application containing the property settings for the application itself, with a single subordinate that is the application's main assembly.

The 'package' entity has the following attributes:

type= one of: application, catalog, volcache (obsolete), recycle or clipboard.
description= A human-readable description of the package's contents.
uid= An ID assigned to the application at the time it was installed. This ID is an integer value in the range 1..254 and is unique among the applications installed on the same cluseter of servers.
template= 0/1 designating whether the application is a template. IDEA! Supported in AppLogic 1.2.5
user1= Free-form user-defined text intended for specifying billing code.
user2= Free-form user-defined text intended for specifying billing code.

The 'package' entity has the following sub-entities, described in detail further below:

package a reference to another package, which is part of the same application. This is used only if type=application .
class defines a component class, including the name of the component descriptor file.
volume a reference to a volume, defining an application-specific data volume (only in application packages)
protocol defines a protocol filter
resources defines the set of servers on which the application can be scheduled to run; optionally defines the numeric ranges from which IP addresses can be assigned to the components of the application. This is used only in application package descriptors.

The 'package' Sub-entity

The 'package' sub-entity in a package descriptor is a reference to another package. Only application packages can have references to other packages. The references are to catalog packages that are part of the application itself - no references to global catalogs are added to an application's package descriptor.

The following attributes are defined for the 'package' sub-entity:

file= file name of the sub-package, relative to the directory in which the 'parent' package resides.
type= the package type, one of: catalog , recycle or clipboard .

The 'class' Sub-entity

This is a reference to a component class descriptor. The following attributes are defined:

top marks the 'topmost' component of the application. This attribute is used for class references in an application descriptor only. The descriptor for the 'topmost' component (which should be an assembly) is in the application's package descriptor file itself.
singleton specifies that only a single instance of this component can be used in an application. This attribute is usually specified for all 'class' sub-entities found in an application's package descriptor.
file= name specifies the name of the file where the component descriptor is located. The name is relative to the directory where the package descriptor itself is found.

The 'volume' Sub-entity

The volume sub-entity is a reference to a volume image that is directly assigned for use by a component of the application. No attributes are defined for this entity. Volumes defined in this manner are stored with the application itself (e.g., when it is archived, moved or copied). These application volumes are assigned to 'placeholder' volumes of component instances using the regular property setting syntax in an assembly.

Note that the 'volume' entities in a package descriptor are the only explicit reference to volumes that belong to the application. However, each component class defined in the application scope or in an application-specific catalog also implicitly refers to one or more volumes that belong to the same application - each volume listed in such components' descriptors that has the class attribute has a corresponding 'template' volume, considered an integral part of the application.

The 'protocol' sub-entity

This sub-entity is used to define protocol filters. It can appear either in a catalog's package descriptor or in an application package descriptor. If any catalog is used in an application, all filters defined in it are available for use in the application (whether by components coming from that catalog or by components defined in the application itself).

If the same protocol filter is defined in more than one package descriptor, all definitions must match exactly, otherwise an error is reported by the ADL compiler. The well-known protocols' filter definitions are defined in the global catalog that is part of any AppLogic installation; these include: http, ftp, smtp, ssh, etc.

The name of each 'protocol' entity is a name that can be used in the ' protocol= xxx' attribute of a terminal (see the component descriptor syntax).

The 'protocol' subentity has a single attribute: 'filter', with a string value that defines the protocol constraints, e.g.:

   protocol http: filter="tcp_in:80"

Note: the syntax of the protocol filter string is not part of this specification - it is not interpreted by the ADL compiler.

The 'resources' Sub-entity

The 'resources' sub-entity defines what is available for the application to use on the grid of servers on which it is installed. It contains the following sub-entities:

servers the set of servers that is available to the application. 'servers' has these attributes:
min= min_val - minimum number of servers to assign to the application
max= max_val - maximum number of servers to assign to the application
set=" name1,name2, ... " - optional; if specified, defines a subset of servers that the application may use.
mem,
cpu,
bw
Instead of defining specific servers that can be used by the application, restrictions on the amount of resources that can be used by it can be defined using one or more of the 'mem', 'cpu' or 'bw' constraints, which have the same syntax as the corresponding resource sub-entities for a component are define the total amount of the corresponding resource that can be made available to the application.
ip the set of IP addresses available for assignment to terminals of the application's components, defined with these attributes:
base=ipaddr
n=max_addrs
netmask=ipaddr
The n and netmask attributes are optional. If netmask is omitted, it is computed from the high-order byte of the IP address, assuming the standard assignments of class A, B and C addresses. If n is omitted, it is computed from the netmask as the maximum number of valid addresses that the netmask allows for. [TBD: it may be more convenient and less error-prone to use the "base/bits" format instead of the netmask, e.g., to specify a range of 510 addresses, "base=192.168.4.1/23" can be used instead of "base=192.168.4.1,netmask=255.255.254.0"]
The 'ip' sub-entity is optional. If not specified, the AppLogic build system assigns a subrange of IP addresses from the pool of IP addresses defined in the AppLogic configuration file ( applogic.conf ). The global pool of addresses defined in applogic.conf is divided into 256 sub-ranges of equal size, each sub-range is used for one of the installed applications depending on its unique ID number assigned at installation time (see the uid attribute above).

Property Markup Syntax

The property markup syntax is used to identify text in ASCII configuration files of a component as being configurable properties, which are modified automatically to match the component's configuration within the application before the component is started. All files identified in the 'cfgfiles' array in a component are scanned for property markup and updated as needed each time the application is being prepared to start.

ALERT! Note that the property markup is only supported for appliances that use the volfix configuration mode.

General Requirements

A configuration file is eligible for inserting property markup into it, if the file's syntax meets the following conditions:

  • it is a plain-text file - that is, a file that can be opened and edited by a text editor.
  • if the text file contains multi-byte characters, it uses the UTF-8 encoding, or any similar encoding that, if processed as a stream of bytes, allows interpreting any value in the range of 0-127 as the corresponding latin ASCII character, regardless of context.
  • the file format allows for inserting comments that are transparent to the component's code that uses the configuration file; the comment syntax is such that comments can be placed sufficiently close to the property values that are being instrumented.
  • within a comment, the characters [ " $ : , -\ ] do not serve as terminators of the comment block and are not interpreted in any other special way.
  • no properties need to be configured to have the newline character as part of their value.
  • if newline is not the terminator for a comment block, then in the normal text the file format must allow for encodig all characters that are part of a comment terminator in a way that they stop looking like a comment terminator.
  • if the file is being read and re-written by anything other than the AppLogic volume fixup utility, the markup comments are preserved and additional newlines are not inserted in the middle of a property value.
  • if the file is being read and re-written by anything other than the AppLogic volume fixup utility, there is a way to ensure that during a re-write, no new text is inserted between a markup comment and the property values to which it refers.

The following file formats are known to comply with the above requirements, and are therefore "instrumentable":

  • Linux line-oriented configuration files (commonly residing in the /etc/ directory and having the .conf suffix), in which lines beginning with the # character are treated as comments.
  • sh/bash and Perl scripts
  • source files in C++ (including header files).
  • source files in C, when compiled by GCC or another compiler that allows the C++ single-line comments (//).
  • HTML and similar SGML files

To handle non-instrumentable files, the recommended approach is to write a bash (or Perl) script that updates the config file on boot and instrument the script itself.

Markup Styles

Inline markup:

$$prop: val1 : name1 , val2 : name2 , ...

The presence of a $$prop: string on a line of text in the configuration file means that this line contains one or more property values. Usually, the "$$prop:" string and the rest of the line of text are made invisible to the application that uses this configuration file by making it appear as a comment, e.g., if the configuration file is a Perl script this might look like:

$port = 3306 # $$prop: 3306:ip_port

The val:name pairs following the markup identifier string are interpreted as follows:

val1:name1 indicates that the first occurrence of the string val1 on this line is to be treated as the value of the property name1 and replaced whenever that property needs to be changed.

val2:name2 indicates that the first occurrence of the string val2 following the first occurrence of val1 is the value of the property name2.

etc.
If the name in a val:name pair is the string '-', the string 'val' is simply ignored. This is used to skip parts of the configuration data that might otherwise match a property value, e.g., a markup like this:

x1 = 1 # $$prop: 1:val

will cause the '1' in x1 to be considered the value of the property 'val'. To make the string '1' that follows the = sign be the property value, the markup has to be:

x1 = 1 # $$prop: 1:-, 1:val

The special '-' property name is also used in case the property value is the empty string, e.g., in the following markup the property is the empty string that follows the "x1 = " string:

x1 = #$$prop: "x1 = ":- , "":val

If a value contains punctuation characters that are part of the markup syntax (colon, comma, space), the value must be quoted, using the double-quote syntax that is defined for the ADL descriptor files.

Next line markup:

$$propN: val1 : name1 , val2 : name2 , ... [$$]

This markup is used for configuration files that do not allow comment text to appear on the same line as the value that needs to be exposed as a modifiable property. It is similar to the inline syntax, but it indicates that the text on the line that follows the one on which the markup appears is to be searched for matching strings, not the current line.

Markup for files that are not line-oriented:

$$propF: val1 : name1 , val2 : name2 , ... $$

This markup is used for configuration files in which the newline character is not considered different from other whitespace and updates of the file may cause newlines to be added or removed at any place where un-quoted whitespace occurs. For this type of markup, a closing $$ sequence is required to indicate the end of the list of val:name pairs. Newlines are allowed between the val:name pairs. All text following the closing $$ mark, regardless of newlines is searched for strings matching the values, until all values are found or until 1K of text is read for each val:name pair (if the latter occurs without finding all values, an error is reported). Note that each property value is still expected to reside on a single line.

Meta-character Quoting in Configuration Files

Some configuration files allow characters that have a special meaning (meta-characters) to be quoted in a way that they lose their special meaning and become part of normal data. The ADL property update code in the Volume Fixup utility is aware of quoting and will maintain it when property values are updated.

Whenever a property value contains such "escaped" characters, they must appear in the same exact way both in the markup (which is inside a comment section in the file) and in the actual text, even if these characters need to be "escaped" only in the normal config file text (or only in the comment). For example, the & character doesn't have a special meaning in HTML comments, but it has to be "escaped" in HTML data, i.e.:

<!-- $$propF "&":my_prop $$ --><sometag someattr="text &amp; more text">

is not valid, even though "&" is OK to appear in the comment, and must be re-done this way:

<!-- $$propF "&amp;":my_prop $$ --><sometag someattr="text &amp; more text">

The quoting of the data values may be in different formats, depending on the file type, as specified by the 'quoting=' attribute (see the component descriptor syntax). This quoting is independent of the C-style double quotes used by the markup syntax itself to enclose a property value - the latter is always done with the C-style double quotes and is superimposed on top of the former, e.g., the string 'abc"def', which may be quoted as abc\"def for a C file, will appear as follows in the markup:

p = "abc\"def"; // $$prop "abc\\\"def":p_val

Appendix

Future Directions

Per-property quoting style override

The component descriptor syntax allows specifying a single quoting style for a config file, which applies to the entire file. This may not be sufficient to cover for cases when a single file has two or more meta-character quoting methods, depending on context (e.g., in an HTML style, regularly the &...; sequence is used to quote special characters, but in URLs the %xx hex-coded quoting is used.

To provide for cases like this, a per-property override can be defined as an extension of the markup syntax, e.g.:
$$prop value:prop-name(quote-style), ...

More quoting styles

Additional meta-character quoting styles can be added in the future, including:

  • user-defined styles (e.g., specified as perl-style replacement commands like: s/&/&amp;/)

  • pre-defined styles:
    makefile : \<LF> is encoded as \#<LF>, trailing whitespace (<SP><LF>) is encoded as <SP>#<LF>, leading whitespace is not encodeable and is forbidden.
    xml : TBD, should be similar to HTML.

Unresolved

"Fixing" the device name for the "external" interface.

The statement found in the text describing the 'interface' sub-entity in a component descriptor says that it is always assigned to the 'eth0' device. This makes the definition of the 'interface external: ...' syntax construct Linux-specific. Also, in Linux it isn't a requirement that an interface of that name exists, either - I, for one, have a setup with a single network interface named 'ath0'.

Global ".failover" group IDs

The failover group ID defined in this specification is global to the application. This may cause conflicts if it is used in instantiable assemblies that are located in a catalog - possibly making unrelated components to "avoid" each other unnecessarily if the same ID was used in two different assemblies without intent to make the components in them belong to the same "failover" group. A safer alternative may be to make the failover group IDs local to an assembly.


Included topics, for easier editing: AdvADLDescriptorTypes AdvADLSyntaxRulesGeneral AdvADLComponentDescriptor AdvADLAssemblyDescriptor AdvADLPackageDescriptor AdvADLPropertyMarkup AdvADLAppendix

-- VladM - 25 May 2006

 
Copyright © CA 2005-2011. All Rights Reserved.
%