For IAM feature design goal, you can take a look at our FS at https://cwiki.apache.org/confluence/display/CLOUDSTACK/CloudStack+Identity+ and+Access+Management+%28IAM%29+Plugin. Also Prachi and I presented this work at Denver Apache CloudStack Collab conference, you can also view our slideshare at http://events.linuxfoundation.org/sites/events/files/slides/ApachIAM.pdf and view the recorded presentation at https://www.youtube.com/watch?v=iUThjMl2yl8&list=PLU2OcwpQkYCyPx_cwJxyOK0YK SM86Mj9n&index=24.
Hope that those pointers can provide some help. -min On 11/18/14 11:26 AM, "Leo Simons" <lsim...@schubergphilis.com> wrote: >Hi Min, > >Thanks for a very clear answer! > >However, I'm afraid I still don't get it :-). So... > >...do you have any specific example or use case of an external IAM >service to integrate with? Is there some kind of design document for me >to understand the goals? > >I ask because all the ones that I'm familiar with tend to assume that the >owner of identity information (and grouping, and possibly other kinds of >AAA assertions) is externalized from systems like cloudstack to the >identity system, i.e. integration is "the other way around". > >So i.e. you would have AD or other LDAP or an SSO server or a SAML >implementation (or all of those...), where systems like cloudstack then >delegate AAA questions/assertions to those systems, rather than >propagating local identities to that central system. > >I imagine if you have an external identity provider, you plug in a >different implementation of AccountManager (LDAPAccountManager? etc.), >and then a CreateAccountCmd would fail with an error saying the server is >configured to use <<external thing>> so account creation is unsupported. > > >cheers! > > >Leo > > >On Nov 18, 2014, at 7:50 PM, Min Chen <min.c...@citrix.com> wrote: >> Hi Leo, >> >> "NO EVENT PUBLISH CAN BE WRAPPED WITHIN DB TRANSACTION!" is along the >> same line as "NO AGENT COMMAND CAN BE WRAPPED WITHIN DB TRANSACTION!". >>The >> rationale behind this is simple: event subscriber execution or agent >> command handling at resource layer may take too long, and we don't want >>to >> have that long transaction window to hold DB for too long. >> As for your questions about why we bother to use message bus to >> communicate between two java component, there is a reason for it: loose >> coupling. IAMApiServiceImpl is a class in IAM plugin service, which can >>be >> deployed as a totally different service from CloudStack management >>server >> and ideally with future 3rd-party authentication/authorization >> integration, they may use a totally different database from "cloud" >> database we are currently using just for simplicity. In this deployment >> architecture, we have to make sure that this IAM service and CloudStack >>MS >> components are loosely coupled. Message bus provided us a very good >> approach to achieve that. >> As you said, ideally we would like to achieve a prefect transaction >> related to account creation in both CloudStack main component and its >> plugin services, but in reality, this may not work always and big >> transaction will be error-prone for large scale distributed systems, >> especially for this loosely coupled components that are crossing >>different >> DBs. The plugin architecture in CloudStack is designed to easily >> enable/disable each plugin component without impacting too much on main >> CloudStack components. So in this case, I would personally prefer that >>we >> should make sure of data integrity in the scope of CloudStack main >> components first and handle potential message handling failure in plugin >> module separately through application level logic. >> >> Thanks >> -min >> >> >> >> On 11/18/14 5:52 AM, "Leo Simons" <lsim...@schubergphilis.com> wrote: >> >>> Hi Min, hi Koushik, >>> >>> Cloudstack is shouting at me: >>> NO EVENT PUBLISH CAN BE WRAPPED WITHIN DB TRANSACTION! >>> >>> (full stack trace below). I've learned this is happening on our >>> systemvm-persistent-config feature branch because it has commit >>> ffaabdc13fde0f0f7b2667a483006e2a4b805f63 but it does not have commit >>> f585dd266188a134a9c8b911376b066b9d3806e8 yet. >>> >>> I'm now trying to understand what's happening here -- the transaction / >>> concurrency / messaging logic gave me significant headache with its >>> triple negatives, nested transaction scoping and home-grown gates, but >>>I >>> think I got it now. >>> >>> As I understand it, in the olde world, creating an account: >>> >>> * opens a database transaction >>> * creates an account in the db >>> * creates the first user in that account in the db >>> * publishes an event >>> * which is listened to by 0 subscribers >>> * commmits the database transaction >>> * check the user is there >>> * opens a database transaction >>> * find the created user in the database >>> * (auto)closes transaction >>> * returns success if the user is in the db >>> >>> this, err, works, but in some other cases, apparently, there are >>>concerns >>> that the db transaction is open too long while message handling >>>happens. >>> So that's why the warning was added, and follow up on, and so now, >>> creating an account: >>> >>> * opens a database transaction >>> * creates an account in the db >>> * creates the first user in that account in the db >>> * commmits the database transaction >>> * publishes an event >>> * which is still listened to by on average 0 subscribers, >>> but there could be an IAM subscriber >>> * check the user is there >>> * opens a database transaction >>> * find the created user in the database >>> * (auto)closes transaction >>> * returns success if the user is in the db >>> >>> The one possible subscriber for account creation is IAMApiServiceImpl, >>> which when receiving the event >>> >>> * opens a database transaction >>> * adds the account to acl_group_account_map >>> * commits the database transaction >>> * finds the domain for the account >>> * opens a database transaction >>> * finds the domain for the account >>> * (auto)closes transaction >>> * finds the domain groups for the domain >>> * opens a database transaction >>> * finds the domain groups for the domain >>> * (auto)closes transaction >>> * for each domain group >>> * opens a database transaction >>> * adds the account to acl_group_account_map >>> * commits the database transaction >>> >>> in other words, if there's 1 domain group and an enabled IAM thingie, >>> this spreads out "make an account" over 6 transactions. Without IAM >>> thingie its 2 two transactions with a no-op message bus thingie in the >>> middle. Is that correct? >>> >>> If so, I don't understand this at all. The pre-November code doesn't >>>make >>> that much sense to me (why query the database? If you don't trust your >>> database its ACID guarantees...why use transactions? Why do we ever >>>need >>> a message bus between two java components in the same classloader?), >>>but >>> the new code scares me. >>> >>> In the case of errors in between transactions, you can end up with >>> accounts that are not in all the groups they should be in. I imagine I >>> would much rather see the whole thing fail, and the complete api call >>> fail, so that I can re-try it as a whole, than end up with a somehow >>> half-initialized account. I.e. have everything account-management-y >>> happen in one transaction which is rolled back on any failure. >>> >>> Any thoughts? >>> >>> >>> Thanks! >>> >>> >>> Leo (who can't ask Hugo since Hugo is at apachecon/ccceu and he isn't >>>:)) >>> >>> >>> 2014-11-18 13:36:33,145 ERROR [o.a.c.f.m.MessageBusBase] >>> (qtp1734055321-25:ctx-05df2079 ctx-25ea4461 ctx-3aac3268) >>> NO EVENT PUBLISH CAN BE WRAPPED WITHIN DB TRANSACTION! >>> com.cloud.utils.exception.CloudRuntimeException: >>> NO EVENT PUBLISH CAN BE WRAPPED WITHIN DB TRANSACTION! >>> at >>> >>>org.apache.cloudstack.framework.messagebus.MessageBusBase.publish(Messag >>>eB >>> usBase.java:167) >>> at >>> >>>com.cloud.user.AccountManagerImpl$2.doInTransaction(AccountManagerImpl.j >>>av >>> a:1052) >>> at >>> >>>com.cloud.user.AccountManagerImpl$2.doInTransaction(AccountManagerImpl.j >>>av >>> a:1027) >>> at >>>com.cloud.utils.db.Transaction$2.doInTransaction(Transaction.java:57) >>> at com.cloud.utils.db.Transaction.execute(Transaction.java:45) >>> at com.cloud.utils.db.Transaction.execute(Transaction.java:54) >>> at >>> >>>com.cloud.user.AccountManagerImpl.createUserAccount(AccountManagerImpl.j >>>av >>> a:1027) >>> at sun.reflect.GeneratedMethodAccessor181.invoke(Unknown Source) >>> at >>> >>>sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessor >>>Im >>> pl.java:43) >>> at java.lang.reflect.Method.invoke(Method.java:606) >>> at >>> >>>org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection( >>>Ao >>> pUtils.java:317) >>> at >>> >>>org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinp >>>oi >>> nt(ReflectiveMethodInvocation.java:183) >>> at >>> >>>org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Ref >>>le >>> ctiveMethodInvocation.java:150) >>> at >>> >>>org.apache.cloudstack.network.contrail.management.EventUtils$EventInterc >>>ep >>> tor.invoke(EventUtils.java:106) >>> at >>> >>>org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Ref >>>le >>> ctiveMethodInvocation.java:161) >>> at >>> >>>com.cloud.event.ActionEventInterceptor.invoke(ActionEventInterceptor.jav >>>a: >>> 51) >>> at >>> >>>org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Ref >>>le >>> ctiveMethodInvocation.java:161) >>> at >>> >>>org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(E >>>xp >>> oseInvocationInterceptor.java:91) >>> at >>> >>>org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(Ref >>>le >>> ctiveMethodInvocation.java:172) >>> at >>> >>>org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAo >>>pP >>> roxy.java:204) >>> at com.sun.proxy.$Proxy108.createUserAccount(Unknown Source) >>> at >>> >>>org.apache.cloudstack.api.command.admin.account.CreateAccountCmd.execute >>>(C >>> reateAccountCmd.java:178) >>> at com.cloud.api.ApiDispatcher.dispatch(ApiDispatcher.java:141) >>> at com.cloud.api.ApiServer.queueCommand(ApiServer.java:691) >>> at com.cloud.api.ApiServer.handleRequest(ApiServer.java:514) >>> at >>>com.cloud.api.ApiServlet.processRequestInContext(ApiServlet.java:273) >>> at com.cloud.api.ApiServlet$1.run(ApiServlet.java:117) >>> at >>> >>>org.apache.cloudstack.managed.context.impl.DefaultManagedContext$1.call( >>>De >>> faultManagedContext.java:56) >>> at >>> >>>org.apache.cloudstack.managed.context.impl.DefaultManagedContext.callWit >>>hC >>> ontext(DefaultManagedContext.java:103) >>> at >>> >>>org.apache.cloudstack.managed.context.impl.DefaultManagedContext.runWith >>>Co >>> ntext(DefaultManagedContext.java:53) >>> at com.cloud.api.ApiServlet.processRequest(ApiServlet.java:114) >>> at com.cloud.api.ApiServlet.doPost(ApiServlet.java:81) >>> at javax.servlet.http.HttpServlet.service(HttpServlet.java:707) >> >