Pattern-type (Part 18): Create multiple VMs for the same component

I got a question: “Can I create multiple VMs for a given component?”. Imagine you have an application component that needs extra VMs if some policies are set! I don’t want to bother the pattern designer with some extra rules and tell him “if you define this policy you absolutely need to add an extra VM in order to manage this policy”.

In this article, I will explain how to create an extra VM if the scaling policy is defined for the component.

Here the two pattern with and without policy:
Without Policy:

SCAWS 2VM Pattern No ScalingWith Policy:

SCAWS 2VM Pattern with scaling

 

and the result we would like to have:
Without Scaling: SCAWS 2VM Running Pattern No ScalingWith Scaling:

SCAWS 2VM Running Pattern With ScalingTo get this behavior here the different steps:

1) Define the appmodel
In the appmodel/metadata.json we have to define the component which will generate 2 VMs at the end of the day if a scaling policy is defined. So, we define the component and the scaling policy:

[
   {
      "id": "MainVM",
      "type": "component",
      "label": "MainVM"
   },
    {
        "id": "ScalingPolicy",
        "label": "Main Server scaling policy",
        "type": "policy",
        "applicableTo": [
            "MainVM"
        ],
        "description": "Slave Server scaling policy",
        "groups": [
            {
                "category": "Scaling Type",
                "id": "None",
                "label": "Static",
                "defaultValue": true,
                "attributes": [
                    "intialInstanceNumber"
                ],
                "description": "Description for the Slave scaling policy."
            }
        ],
        "attributes": [
            {
                "id": "intialInstanceNumber",
                "label": "Number of Instances",
                "type": "number",
                "min": 1,
                "required": true,
                "sampleValue": 1,
                "invalidMessage": "This value is required, its valid value greater or equal to 1",
                "description": "Specifies the number of cluster members that are hosting the web application. The default value is 1. Acceptable values range from 1-n."
            }
        ]
    }
]

2) Define the packages:
In the config.json we have to define the packages that will be use to deploy the 2 VMs.

{
    "name":"plugin.com.itdove.onecomp.twovm",
    "version" : "1.0.0.2",
    "patterntypes":{
        "primary":{
            "patterntypeOneCompTwoVM":"1.0"
        }
    },
    "packages":{
        "MainVMPKG": [
            {
				"requires":{
					"arch":"x86_64"
				},                
				"parts": [
                    {
                        "part": "parts/MainVMPKG.tgz"
                    }
                ]
            } 
        ],
        "SecondaryVMPKG": [
            {
				"requires":{
					"arch":"x86_64"
				},                
                "parts": [
                    {
                        "part": "parts/SecondaryVMPKG.tgz"
                    }
                ]
            }
        ]
    }
}

3) Create the roles:
We create 2 roles, one for the MainVM and a second one for the extra VM we would like to deploy (one in each package):SCAWS 2VM Roles

4) Define the topology:
Now we have to create the topology for the MainVM:

{
#set( $spattrs = $provider.getPolicyAttributes($component, "ScalingPolicy") )
    "vm-templates": [
        {
            "scaling":{
#if_value( $spattrs, "intialInstanceNumber", '"min": $value,')
#if_value( $spattrs, "intialInstanceNumber", '"max": $value')
            },
            "name": "${prefix}-MainVM",
            "roles": [
                {
                    "type": "MainVM",
                    "name": "Main",
        			"dashboard.visible":true
                }                 
            ],

            "packages":["MainVMPKG"]
        }
#if ($spattrs)
        ,         
        {
            "name": "${prefix}-SecondaryVM",
            "roles": [
                {
                    "type": "SecondaryVM",
                    "name": "Secondary",
        			"dashboard.visible":true
                }                 
            ],

            "packages":["SecondaryVMPKG"]
        }    
#end
    ]
}

In this topology, you can see that we test if the scaling policy is set to create the secondary VM.

Now, don’t forget to add the OSGI element (ie: mainvm.vm)

xmlns:scr=”http://www.osgi.org/xmlns/scr/v1.1.0″ name=”MainVM”>;
<implementation />;
<service>
<provide interface=”com.ibm.maestro.model.transform.TopologyProvider” />
</service>
<property name=”component.template” type=”String” value=”templates/mainvm.vm” />
</scr:component>

and update the MANIFEST.MF to add this new service.