brooklyn-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Aled Sage (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (BROOKLYN-351) extra jclouds providers not found (in karaf)
Date Mon, 26 Sep 2016 12:29:20 GMT

    [ https://issues.apache.org/jira/browse/BROOKLYN-351?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15522913#comment-15522913
] 

Aled Sage commented on BROOKLYN-351:
------------------------------------

I see two possible solutions:

1. Remove the store from {{JcloudsLocationResolver}}, to always query jclouds.

2. Make the store more sophisticated: just store the {{org.jclouds.providers.Providers.fromServiceLoader}},
and delegate each time to {{ProviderRegistry.fromRegistry()}} (because that is dynamically
updated when bundles are added/removed).

For (1), the potential downside is a performance hit: {{Providers.withId(String)}} will call
{{ServiceLoader.load(ProviderMetadata.class)}} each time, which will scan the current thread's
context class loader.

Doing a quick test in {{brooklyn-server/locations/jclouds}} (so loading 19 providers and 19
APIs from jclouds-allcompute and jclouds-allblobstore), calling it sequentially and repeatedly
(from threads in a thread pool) it took 306ms the first time, 23ms the second time, and then
decreased to about 6ms after approx 100 calls.

Unfortunately, {{isProvider()}} and {{isApi()}} are called by {{JcloudsLocationResolver.accepts()}}
so is called a fair amount. I'm not sure exactly, but I presume it's called when parsing catalog
items at startup, adding new catalog items, and when parsing any locations defined in brooklyn.properties.
Hopefully that's mostly just a hit at startup.

Given that (2) may not be worth the effort, I suggest we go with the simpler code in (1).
If it does impact performance (particularly if it's called when polling the REST api for the
list of catalog locations etc), then we'd need to revisit.

If we ever did want to retrieve and store the {{ServiceLoader}} results, we could add code
like that below (untested):

{noformat}
public class JcloudsProviderAndApiLoader {
    private enum LazyServiceLoader {
        INSTANCE;

        public final Map<String,ProviderMetadata> providers;
        public final Map<String,ApiMetadata> apis;
        
        LazyServiceLoader() {
            Map<String,ProviderMetadata> providersTmp = Maps.newLinkedHashMap();
            for (ProviderMetadata p: Providers.fromServiceLoader()) {
                providersTmp.put(p.getId(), p);
            }
            providers = ImmutableMap.copyOf(providersTmp);
            
            // Unfortunately Apis.fromServiceLoader() is private
            Map<String,ApiMetadata> apisTmp = Maps.newLinkedHashMap();
            ServiceLoader.load(ApiMetadata.class);
            for (ApiMetadata p: ServiceLoader.load(ApiMetadata.class)) {
                apisTmp.put(p.getId(), p);
            }
            apis = ImmutableMap.copyOf(apisTmp);
        }
    }
    
    public boolean isProvider(String id) {
        return getProvider(id).isPresent();
    }

    public boolean isApi(String id) {
        return getApi(id).isPresent();
    }
    
    public Optional<ProviderMetadata> getProvider(String id) {
        if (LazyServiceLoader.INSTANCE.providers.containsKey(id)) {
            return Optional.of(LazyServiceLoader.INSTANCE.providers.get(id));
        }
        return Iterables.tryFind(ProviderRegistry.fromRegistry(), ProviderPredicates.id(id));
    }

    public Optional<ApiMetadata> getApi(String id) {
        if (LazyServiceLoader.INSTANCE.apis.containsKey(id)) {
            return Optional.of(LazyServiceLoader.INSTANCE.apis.get(id));
        }
        return Iterables.tryFind(ApiRegistry.fromRegistry(), ApiPredicates.id(id));
    }
}
{noformat}


> extra jclouds providers not found (in karaf)
> --------------------------------------------
>
>                 Key: BROOKLYN-351
>                 URL: https://issues.apache.org/jira/browse/BROOKLYN-351
>             Project: Brooklyn
>          Issue Type: Bug
>            Reporter: Aled Sage
>
> When using a downstream build of Brooklyn 0.10.0-SNAPSHOT (with karaf), I added a couple
of extra jclouds labs providers/apis via the feature.xml.
> However, when I tried to use it with the blueprint below, I got the error shown:
> {noformat}
> location: jclouds:azurecompute
> services:
> - type: org.apache.brooklyn.entity.stock.BasicApplication
> 2016-09-26 12:10:12,346 DEBUG 115 o.a.b.c.t.AbstractTypePlanTransformer [p1212877220-1463]
Could not instantiate BasicRegisteredType[null;null] (rethrowing): Illegal parameter for 'location'
(jclouds:azurecompute); not resolvable: NoSuchElementException: Cloud provider/
> API type azurecompute is not supported by jclouds
> {noformat}
> Looking in {{org.jclouds.providers.Providers.withId("azurecompute")}}, jclouds does know
about azurecompute.
> The problem is that the providers/apis list are retrieved and stored in {{JcloudsLocationResolver.PROVIDERS}}
and {{JcloudsLocationResolver.APIS}} (during static init). At that point, the azurecompute
bundle has not been activated, so {{org.jclouds.osgi.ProviderRegistry}} had not yet had it
added by {{org.jclouds.osgi.MetadataBundleListener}}.
> Below is a stacktrace of where this happens:
> {noformat}
> Daemon Thread [FelixStartLevel] (Suspended (breakpoint at line 82 in Providers))	
> 	owns: AtomicBoolean  (id=1573)	
> 	Providers.all() line: 82	
> 	JcloudsLocationResolver.getProvidersMap() line: 61	
> 	JcloudsLocationResolver.<clinit>() line: 56	
> 	NativeConstructorAccessorImpl.newInstance0(Constructor, Object[]) line: not available
[native method]	
> 	NativeConstructorAccessorImpl.newInstance(Object[]) line: 57	
> 	DelegatingConstructorAccessorImpl.newInstance(Object[]) line: 45	
> 	Constructor<T>.newInstance(Object...) line: 526	
> 	ReflectionUtils.newInstance(AccessControlContext, Constructor, Object...) line: 331

> 	BeanRecipe.newInstance(Constructor, Object...) line: 984	
> 	BeanRecipe.getInstanceFromType(List<Object>, List<ReifiedType>) line: 349

> 	BeanRecipe.getInstance() line: 282	
> 	BeanRecipe.internalCreate2() line: 830	
> 	BeanRecipe.internalCreate() line: 811	
> 	BeanRecipe(AbstractRecipe).create() line: 106	
> 	RefRecipe.internalCreate() line: 62	
> 	RefRecipe(AbstractRecipe).create() line: 106	
> 	ServiceRecipe.createService() line: 285	
> 	ServiceRecipe.internalGetService(Bundle, ServiceRegistration) line: 252	
> 	ServiceRecipe.internalCreate() line: 149	
> 	AbstractRecipe$1.call() line: 79	
> 	FutureTask<V>.run() line: 262	
> 	ServiceRecipe(AbstractRecipe).create() line: 88	
> 	BlueprintRepository.createInstances(Collection<String>) line: 255	
> 	BlueprintRepository.createAll(Collection<String>) line: 186	
> 	BlueprintContainerImpl.instantiateEagerComponents() line: 712	
> 	BlueprintContainerImpl.doRun() line: 399	
> 	BlueprintContainerImpl.run() line: 273	
> 	BlueprintExtender.createContainer(Bundle, List<Object>) line: 294	
> 	BlueprintExtender.createContainer(Bundle) line: 263	
> 	BlueprintExtender.modifiedBundle(Bundle, BundleEvent, Object) line: 253	
> 	BundleHookBundleTracker$Tracked.customizerModified(Bundle, BundleEvent, T) line: 500

> 	BundleHookBundleTracker$Tracked.customizerModified(Object, Object, Object) line: 433

> 	BundleHookBundleTracker$Tracked(BundleHookBundleTracker$AbstractTracked<S,T,R>).track(S,
R) line: 725	
> 	BundleHookBundleTracker$Tracked.bundleChanged(BundleEvent) line: 463	
> 	BundleHookBundleTracker$BundleEventHook.event(BundleEvent, Collection) line: 422	
> 	SecureAction.invokeBundleEventHook(EventHook, BundleEvent, Collection<BundleContext>)
line: 1179	
> 	EventDispatcher.createWhitelistFromHooks(EventObject, Framework, Map<BundleContext,List<ListenerInfo>>,
Map<BundleContext,List<ListenerInfo>>, Class<T>) line: 731	
> 	EventDispatcher.fireBundleEvent(BundleEvent, Framework) line: 486	
> 	Felix.fireBundleEvent(int, Bundle) line: 4541	
> 	Felix.startBundle(BundleImpl, int) line: 2172	
> 	Felix.setActiveStartLevel(int, FrameworkListener[]) line: 1371	
> 	FrameworkStartLevelImpl.run() line: 308	
> 	Thread.run() line: 745	
> {noformat}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Mime
View raw message