| United States-English |
|
|
|
![]() |
HP WBEM Services Software Developer's Kit for HP-UX Provider and Client Developer's Guide > Chapter 4 Provider ImplementationProvider Design Considerations |
|
The following is a high-level description of the control flow of a client request:
A provider module is implemented as a shared library. The CIM Server loads the shared library and initializes the provider on demand (on the first access of an object served by the provider). In HP WBEM Services for HP-UX, the provider functions are called in the process context of the CIM Server. However, the provider must not assume that it is running in the same process as the CIM Server. The process context in which a provider runs is determined by the CIM Server, and is not configurable. This means that it is not possible to set environment variables, working directory, permission mask, or any other environment parameters before a provider is activated. Furthermore, the provider must not set any of these during operation. If it is necessary to do so for correct operation, the provider should create a separate process with the needed environment, and communicate with this process by any suitable means of interprocess communication (for example, pipes, shared memory, files, or another mechanism). Providers run under the root user ID in HP WBEM Services for HP-UX. However, developers must not assume that this will continue to be true in future releases. Please refer to the section on “Security Architecture” for more information. Providers built for IPF deployment should be compiled as native programs. They will not work if compiled in emulation mode. Provider source code is compiled and linked to build a shared library. The CIM Server will call the functions in this shared library when a client requests an operation on a CIM object that the provider instruments. The CIM Server finds the shared library containing the provider for a particular CIM object by searching the Provider Registrations that it was supplied when providers were installed. Provider Registration consists of CIM instances of three classes of objects, all defined in the root/PG_InterOp namespace:
The PG_ProviderModule object corresponds to a single shared library. Example 4-1 shows its definition, in a MOF declaration: Example 4-1 PG_ProviderModule: An abridged MOF declaration
A shared library (provider module) may contain more than one provider. This can simplify sharing code among several providers that must use the same system services to perform their operations. The name of the shared library file must be of the form lib<library-name>.sl where <library-name> is the string specified in the Location property of an instance of PG_ProviderModule. The shared library file may reside in any directory on the system, but a symbolic link to the file must exist in /opt/wbem/providers/lib in order for the CIM Server to find it. The Name property of PG_ProviderModule is an arbitrary string that will be referenced in instances of PG_Provider and PG_ProviderCapabilities. Like the Location property (and the shared library name), it is advisable to use the word Module in the string. Example 4-2 PG_ProviderModule: Instance shown in MOF
The Location property is used to construct the path of the shared library containing the provider module as described in Figure 4-2, above. The extension is either .sl or .so, depending on the platform:
The InterfaceType and InterfaceVersion properties are required with the values exactly as shown in order to allow possible future implementations to support different provider interface protocols and versions. The PG_Provider object identifies a single provider and the PG_ProviderModule in which it can be found. Example 4-3 shows its definition in a MOF declaration: Example 4-3 PG_Provider: an abridged MOF declaration
The ProviderModuleName property is a string whose value must be the same (case insensitive) as the Name property of an instance of PG_ProviderModule. The Name property in PG_Provider is the string the CIM Server will pass to the PegasusCreateProvider function when it needs a pointer to the provider (the first time it calls a function in the provider). Example 4-4 below shows a source fragment with an example of C++ provider class declarations and an implementation of the PegasusCreateProvider function. Example 4-5 shows how an instance of PG_Provider associates a provider name with a provider module corresponding to a shared library. Example 4-4 Provider source fragment showing provider class declarations and implementation of the PegasusCreateProvider entry point
Example 4-5 PG_Provider: A MOF showing an instance
In Example 4.5, the instance of PG_Provider informs the CIM Server that the provider named ProcessStatusProvider will be found in the Provider Module named DynamicInfoModule. For our example, there would be another instance of PG_Provider to tell the CIM Server that the MemoryInfoProvider is also in the DynamicInfoModule. The class PG_ProviderCapabilities is used to associate a provider with the class for which it supplies instances, methods, indications, or associations in the specified namespace. Example 4-6 shows the definition of PG_ProviderCapabilities in a MOF declaration: Example 4-6 PG_ProviderCapabilities: An abridged MOF declaration
As in the PG_Provider object (Example 4-3), the ProviderModuleName tells the CIM Server which module contains the provider that this capabilities instance describes. It must be the same as the Name property of an instance of PG_ProviderModule. Likewise, the ProviderName property must be the same as the Name property of an instance of PG_Provider. The CapabilityID key makes it possible to have several instances naming the same provider and module, but with different capabilities. They might differ in the class that they instrument, or they may name different sets of properties or implement different provider types. However, there can be no more than one Instance Provider for each class in a namespace! There may be more than one Method Provider as long as they do not claim service for the same method. The following descriptions are taken from the complete MOF definition of PG_ProviderCapabilities:
MOF Example 4-7, below, shows a class definition. Example 4-8, following that, shows an instance of PG_ProviderCapabilities that associates the provider with the newly created class: Example 4-7 MOF declaration of the class ACME_ComputerSystem
Example 4-8 PG_ProviderCapabilities: A MOF instance
The instance of PG_ProviderCapabilities in Example 4-8 informs the CIM Server as follows:
The files containing MOF fragments shown above must be loaded into the CIM Server's repository: the files containing provider registration instances must be loaded into the root/PG_InterOp namespace, and the file containing the definition of the ACME_ComputerSystem class must be loaded into a normal, non-system namespace (please refer to the section on “Installing and Running a Provider”). When a client requests an operation to be performed on a class, the CIM Server will examine these instances to determine which provider(s) to call. A Version qualifier should be used on the class definition for ACME_ComputerSystem. This allows a provider installation procedure to determine whether an existing schema definition is a lower version (and can therefore be upgraded) or equal to or greater than the version supported by the new provider (in which case it should not be modified). There is no required relationship between the name of the provider (PG_Provider.Name), the name of the module (PG_ProviderModule.Name), the name of the shared library into which it is built (PG_ProviderModule.Location), and the schema element with which it is associated (PG_ProviderCapabilities.ClassName). However, for clarity, it is useful to choose names that help to identify the element. The conventions evident in the previous example show how this may be done. Most providers manipulate instances or instance references (also called object paths) in some way. The set of all keys of an instance defines the unique identity of an instance within a namespace of managed objects. For example, there are possibly many users whose Name is "smith", but on any given UNIX computer system, there can be only one called "smith." In order to know exactly which user "smith" we are interested in (to address email, for example), we must know the name of the system in question. Therefore, for a user account, a unique identification must include the SystemName as well as the Name (just as an Internet email address is specified as username@domain-name). In this example of a class representing a user account, the SystemName and Name, together, form a set of key properties that uniquely define each instance. In this example, the SystemName is said to specify the context (or scope) in which the Name will be unique. For many classes in the CIM model in which keys are defined, there will be at least one key property to specify the scope of the class's other keys. Keys that specify necessary scope are always propagated from another class of object, as mentioned in the section on Common Properties in Chapter 3, under General Schema Use Cases. The SystemName key present in many CIM classes is propagated from the Name property of the CIM_System class (or one of its subclasses). When scoping keys exist in a class definition, the classes from which the scoping keys are propagated are also specified as key properties. So if there is a SystemName key, there must be a property specifying the name of the class from which the SystemName is obtained. This key is the SystemCreationClassName. For a typical class in the hierarchy of CIM_ManagedSystemElement, (CIM_LogicalDevice, for example), the full set of key properties might be:
It is entirely up to the provider to determine the value of a Name (or analogous) key. The primary requirement is that there may be only one instance of a class with a given key value. If this were not the case, it would be impossible to distinguish between different instances in a given context. Although not a requirement, the value can be chosen to be representative of what a client would expect to see. For example, the name of a disk partition on HP-UX, as displayed by the df command, is often something like /dev/vg00/lvol3, so this would be an appropriate value for the Name property of a disk partition object. The values for SystemCreationClassName and SystemName must be chosen with equal care, since the provider must coexist with other providers on the same platform (indeed, in the same namespace). The values of these properties must be chosen to ensure consistency and avoid conflicts. When the meaning of SystemName is clearly a system's IP hostname (as it will often be), the provider must supply a standard fully qualified Internet hostname. This value is not reliably obtained from the gethostname() library function, but rather from gethostbyname(). The following code fragment illustrates a suitable means to obtain this value: Example 4-9 Code Fragment to obtain value for SystemName
While the full set of keys is necessary to uniquely identify an instance within a namespace, it is useful to allow clients to specify empty strings for key values when there is no ambiguity. For example, when a client submits a getInstance() operation to a CIM Server, it is clear that the value of the SystemName key will normally be the same as the system to which the client has connected. This is especially useful when managing a multi-homed system (a system that may have more than one IP address or DNS name), since the client need not guess the value of SystemName when there can be several different hostnames for the same system. Unless the provider has a reason to require a value for SystemName, it should accept an empty string for this key without returning an error. As a general rule, providers should accept empty strings for any keys that they do not actually require to identify an instance from among those they manage. However, the provider should always supply values for all keys when returning data to the client. The CIM Server can process several client requests in different threads concurrently in the same provider. Therefore, provider code must be 100% thread-reentrant and must avoid/prevent concurrent access of any shared resources. If shared (global) resources are used, access must be serialized by the use of a suitable semaphore (or mutex) to protect the shared resource against modification that could lead to erroneous behavior. This is particularly important in provider interface methods that alter platform behavior, such as modifyInstance(), createInstance(), and deleteInstance(), but applies to any code that manipulates a globally accessible resource or may have a side effect. Information on developing thread-safe applications can be found online in documentation for the aCC C++ compiler at http://www.docs.hp.com. While all providers implement functions of the same names (for example, getInstance()), there is no duplication of symbol names for symbols defined within a C++ provider classes. The C++ compiler generates unique symbols, because the functions are declared in differently named provider classes. However, it is possible to declare global symbols (technically, named ::<name>), and these may indeed "collide" with symbols of the same name. This issue is not unique to C++ nor to HP WBEM Services for HP-UX providers. Care should be taken to avoid the use of global symbol names whenever possible. When necessary, names should be chosen with a component, such as a module name, that will guarantee, or at least increase the probability of, uniqueness. Access to WBEM Services is restricted to users with valid accounts on the system being managed. Requests from remote clients contain a username/password pair that the CIM Server will authenticate. Requests may also be received through a local connection using the connectLocal() function in the Client API. This function does not take username or password arguments. The user ID for a local client request is that of the process issuing the request. In addition to user authentication, if the feature is enabled, the CIM Server performs namespace authorization (this is disabled when the product is installed, but can be enabled with the cimconfig command). There are several namespaces serviced by the CIM Server. Each namespace has an associated list of users who are authorized to access its objects, and what level of access is permitted (read, write, or read+write). The namespace authorization database is managed with the cimauth command, described in the cimauth man page. The section on “Provider Registration and Naming” describes how providers can register to serve classes in multiple namespaces. namespaces are also discussed in Appendix A, CIM Naming Guidelines. Once a client request has been authenticated and authorized, the username is passed to the provider in the OperationContext parameter present in all function calls. No password is passed to the provider. As previously mentioned, providers run under the root user ID. Providers must use the username to determine whether the user has permission to perform the requested operation. This determination must be made in addition to the namespace authorization that the CIM Server may have performed. The provider must not perform any operation that would be unauthorized for the user on whose behalf it is executing the request. While it may seem technically possible, setuid() must never be called in the provider process, since other requests may be running concurrently in other threads (in the same provider or in others that may be loaded in the same process context). If done in a thread-safe manner, it is permissible to create a separate process under a specific user ID. This may be an appropriate design strategy in cases where it is the most or only reliable means of ensuring secure operation. Care should be taken to consider performance and resource utilization. If needed for additional authorization, the namespace of the target object can be obtained from the object identification parameter of the request, as in the API documentation of the HP WBEM Services SDK, in the /opt/wbem/html directory. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||