Introduction to Generic Objects
Last updated
Last updated
Generic Objects are a very useful new feature of CloudForms 4.6 (ManageIQ Gaprindashvili). They allow us to create custom object classes to represent objects that we may work with, but might not necessarily be represented by an out-of-the-box CloudForms / ManageIQ object. An example might be a load balancer, or a software-defined firewall group.
Note
Generic Objects are also known by their Red Hat marketing name of Dynamic Resource Objects
A Generic Object comprises a class definition and one or more instances of that class. The class definition is created from the Generic Object Classes accordion of the Automation -> Automate -> Generic Objects page in the WebUI. Clicking on the Configuration button reveals the option Add a new Generic Object Class.
A Generic Object definition consists of a number of attributes, associations and methods (see screenshot Adding a new Generic Object Class).
The generic object class name and description can be any free-form text, however if the generic object is to have methods, the class name should be compatible with the automate datastore class naming conventions (i.e. no spaces).
One or more attributes for the Generic Object class can be added. Atrributes can be of the following types:
Boolean
Date/Time
Float
Integer
String
Time
One or more associations to other object types (including other generic objects) can be added if required.
One or more methods can be specified in the class definition if required. The methods themselves are defined in the Automate Datastore in a generic object-specific class under /GenericObject/ClassName. The methods and their associated instances must be named as they appear in the generic object class definition (see screenshot Generic Object Methods in the Automation Datastore)
Method names should not clash with existing Rails Active Record method names, for example a method called validate
already exists, and so go_validate
is used in this example.
Note
The Example class from the ManageIQ domain can be copied and used as a template for the generic object class. This is a simple state machine with 4 states:
pre
execute
check_execute
post
The completed go_validate instance is shown in screenshot Completed go_validate Instance.
In addition to creating a generic object class definition using the WebUI, a class definition can be created by POSTing to the RESTful API, as follows:
Once the Generic Object class has been defined, new instances can created from the definition. The following examples illustrate how to do this from Ruby and Ansible:
From Ruby:
From Ansible:
Although generic objects are useful to work with from automate "behind the scenes", they are most versatile when used in conjunction with services. A Ruby method or Ansible playbook can be called from a service provision state machine to create a generic object using values from a service dialog. The following examples illustrate how this can be done.
From Ruby:
From Ansible:
The newly provisioned service will be seen to have an instance of a generic object when viewed in the WebUI (see screenshot Generic Object Instances in Services WebUI Page).
The link is clickable, and if clicked will navigate to a page displaying an overview of all generic objects associated with the service (see screenshot Generic Object Details from Services WebUI Page).
Further details about each generic object are available by clicking on the individual object's link.
Note
When navigating to the details of a generic object from the Services page in the WebUI, the Service page RBAC will not show any associations of that generic object. Associations are only visible when viewing the generic object details from Automation -> Automate -> Generic Objects
Generic object methods can be run from another automate method, as follows:
They can also be triggered from the RESTful API, for example by POSTing a json body specifying an action
to the RESTful URI of the generic object:
Note
POSTing an action to a generic object can run either the generic object's named method, or a button with that name on the generic object. If both a button and method exist with the same name, the button's method will be run.
Values can be returned from a generic object method to a calling method via $evm.root['method_result']
in the called method. For example we could define a method called get_attr1
for a generic object as follows:
This could be called from another Ruby automate method to retrieve the attribute_1
value from the generic object instance, like so:
Generic object methods can also be run from custom buttons applied to the Generic Object object type. When creating a button the Advanced tab object details should specify GenericObject in the System/Process drop-down, and an Attribute of method_name should be defined with the Value being the name of the generic object's method to run (see screenshot Custom Button Definition).
The custom button group and button is then visible from the generic object details page (see screenshot Custom Button on a Generic Object).
Note
At the time of writing custom buttons on generic objects are only visible when the generic object details are displayed from the Services page in the WebUI, and not when viewing the generic object from the Automation -> Automate -> Generic Objects menu (see Bugzilla for further details).
Custom buttons on generic objects cannot display service dialogs when invoked (see Bugzilla for further details).
There is currently no way of deleting an instance of a generic object via the WebUI. This can however be done from Automate using the remove_from_vmdb
method on the generic object itself, or from the API by POSTing the following body to the RESTful URI of the generic object:
Generic Objects aren't automatically deleted when a service containing them is retired, even if the Remove Resources option set to 'Yes' in the service's Retirement tab. In the context of service retirement, only a VM is considered a resource (VMs have their own retirement state machine/workflow).
Fortunately a simple retirement Ansible playbook such as the following will delete all generic objects associated with the service.
This chapter has introduced Generic Objects (also known as Dynamic Resource Objects). It has illustrated how they can be defined and created, both from Ruby automate and Ansible playbook, and how their methods can be created and run.
The next chapter shows a 'real-world' example of their use in modelling a software-defined firewall group.