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