Hi Vanson,

Thanks for reporting this. This has been a known issue causing problems
when updating IaaS parameters. A work-around would be to redeploy the
cartridge definition which forces it to re-build. I haven't tested it
though. Your solution also works, but were you able to look into to the
performance overhead of re-building every time?



On Sun, Sep 20, 2015 at 10:59 AM, Vanson Lim <v...@cisco.com> wrote:

> Stratos developers,
>
> I found an issue where defining an availability "zone" property in a
> partition has no affect on controlling the placement of a VM launched under
> openstack.
>
> The code which builds the template (iaas.initialize) used by jclouds is
> executed only once before stratos appends the availability zone properties
> to the iaas datastructure.
>
> The problem is in the buildIaas() call shown below:
>
>
> https://github.com/apache/stratos/blob/92ff7e9b5800d578a37d6aa82551d60fbdd66529/components/org.apache.stratos.cloud.controller/src/main/java/org/apache/stratos/cloud/controller/iaases/openstack/OpenstackPartitionValidator.java
>
>
> The issue also exists in the cloudstack, ec2, gce and docker variants of
> this function.
>
> @Override
>     public IaasProvider validate(Partition partition, Properties
> properties) throws InvalidPartitionException {
>         try {
>             // validate the existence of the zone and hosts properties.
>             if (properties.containsKey(Scope.region.toString())) {
>                 String region =
> properties.getProperty(Scope.region.toString());
>
>                 if (iaasProvider.getImage() != null &&
> !iaasProvider.getImage().contains(region)) {
>
>                     String msg = "Invalid partition detected, invalid
> region: [partition-id] " + partition.getId() +
>                             " [region] " + region;
>                     log.error(msg);
>                     throw new InvalidPartitionException(msg);
>                 }
>
>                 iaas.isValidRegion(region);
>
>                 IaasProvider updatedIaasProvider = new
> IaasProvider(iaasProvider);
> *                Iaas updatedIaas =
> CloudControllerServiceUtil.buildIaas(updatedIaasProvider);*
>                 updatedIaas.setIaasProvider(updatedIaasProvider);
>
>                 if (properties.containsKey(Scope.zone.toString())) {
>                     String zone =
> properties.getProperty(Scope.zone.toString());
>                     iaas.isValidZone(region, zone);
>
>
> updatedIaasProvider.setProperty(CloudControllerConstants.AVAILABILITY_ZONE,
> zone);
> *                    updatedIaas =
> CloudControllerServiceUtil.buildIaas(updatedIaasProvider);*
>                     updatedIaas.setIaasProvider(updatedIaasProvider);
>                 }
>
>                 updateOtherProperties(updatedIaasProvider, properties);
>                 return updatedIaasProvider;
>             } else {
>
>                 return iaasProvider;
>             }
>         } catch (Exception e) {
>             String msg = "Invalid partition detected: [partition-id] " +
> partition.getId() + e.getMessage();
>             log.error(msg, e);
>             throw new InvalidPartitionException(msg, e);
>         }
>     }
>
>
>     private void updateOtherProperties(IaasProvider updatedIaasProvider,
>                                        Properties properties) {
>         Iaas updatedIaas;
>         try {
> *             updatedIaas =
> CloudControllerServiceUtil.buildIaas(updatedIaasProvider);*
>
>             for (Object property : properties.keySet()) {
>                 if (property instanceof String) {
>                     String key = (String) property;
>                     updatedIaasProvider.setProperty(key,
>                             properties.getProperty(key));
>                     if (log.isDebugEnabled()) {
>                         log.debug("Added property " + key
>                                 + " to the IaasProvider.");
>                     }
>                 }
>             }
> *             updatedIaas =
> CloudControllerServiceUtil.buildIaas(updatedIaasProvider);*
>             updatedIaas.setIaasProvider(updatedIaasProvider);
>         } catch (InvalidIaasProviderException ignore) {
>         }
>
>     }
>
>
>
> buidIaas() calls getIaas() under the covers and only initializes the
> compute template the first time it is called.   buildIaas() is called a
> second time after the availability_zone property is set, and then a
> third/fourth time in updateOtherProperties().
>
> As show below,   getIaas() only calls iaas.initilize() the first time it's
> called.
>
> public class CloudControllerServiceUtil {
>
> ...
>     public static Iaas buildIaas(IaasProvider iaasProvider) throws
> InvalidIaasProviderException {
>         return iaasProvider.getIaas();
>     }
> ....
>
> public class IaasProvider implements Serializable {
> ....
>     public Iaas getIaas() {
>         if (iaas == null) {
>             synchronized (IaasProvider.this) {
>                 if (iaas == null) {
>                     try {
>                         iaas =
> CloudControllerUtil.createIaasInstance(this);
>                         iaas.initialize();
>                     } catch (InvalidIaasProviderException e) {
>                         throw new RuntimeException("Could not create IaaS
> instance", e);
>                     }
>                 }
>             }
>         }
>         return iaas;
>     }
> ....
>
> I propose the attached diffs to define buildIaas() such that it forces the
> iaas datastructure to be reinitialized,  if this looks okay, I'll see about
> getting this pushed upstream.
> I've also validated this on my openstack setup.
>
>
> Regards,
>
> -Vanson
>
>


-- 
Akila Ravihansa Perera
WSO2 Inc.;  http://wso2.com/

Blog: http://ravihansa3000.blogspot.com

Reply via email to