<font face="Default Sans Serif,Verdana,Arial,Helvetica,sans-serif" size="2"><div class="gmail_default" style="font-family: 'trebuchet ms', sans-serif;"><br></div><div class="gmail_default" style="font-family: 'trebuchet ms', sans-serif;">I think we're arguing for the same thing, but maybe slightly different approach. I think we can both agree that a middle-layer is required, whether we intend to use it as a proxy or REST endpoints. Regardless of the approach, the client needs to relay what API it wants to invoke, and you can do that either via RPC or REST. I personally prefer the REST approach because it shields the client. Client just needs to know which URL to hit in order to invoke a certain API, and does not need to know the procedure name or parameters ordering. Having said all of that, I do believe we should keep it as thin as possible. I do like the idea of having separate classes for different API versions. What we have today is a thin REST layer that acts like a proxy. You hit a certain URL, and the middle layer forwards the API invokation. The only exception to this rule is support for batch deletions.</div><br><font color="#990099">-----Tihomir Trifonov <t.trifonov@gmail.com> wrote: -----</font><div class="iNotesHistory" style="padding-left:5px;"><div style="padding-right:0px;padding-left:5px;border-left:solid black 2px;">To: "OpenStack Development Mailing List (not for usage questions)" <openstack-dev@lists.openstack.org><br>From: Tihomir Trifonov <t.trifonov@gmail.com><br>Date: 12/10/2014 03:04AM<br>Subject: Re: [openstack-dev] [horizon] REST and Django<br><br><div dir="ltr"><div class="gmail_default" style="font-family:trebuchet ms,sans-serif">Richard, thanks for the reply,</div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif"><br></div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif"><br></div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif">I agree that the given example is not a real REST. But we already have the REST API - that's Keystone, Nova, Cinder, Glance, Neutron etc, APIs. So what we plan to do here? To add a new REST layer to communicate with other REST API? Do we really need Frontend-REST-REST architecture ? My opinion is that we don't need another REST layer as we currently are trying to go away from the Django layer, which is the same - another processing layer. Although we call it REST proxy or whatever - it doesn't need to be a real REST, but just an aggregation proxy that combines and forwards some requests with adding minimal processing overhead. What makes sense for me is to keep the authentication in this layer as it is now - push a cookie to the frontend, but the REST layer will extract the auth tokens from the session storage and prepare the auth context for the REST API request to OS services. This way we will not expose the tokens to the JS frontend, and will have strict control over the authentication. The frontend will just send data requests, they will be wrapped with auth context and forwarded.</div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif"><br></div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif">Regarding the existing issues with versions in the API - for me the existing approach is wrong. All these fixes were made as workarounds. What should have been done is to create abstractions for each version and to use a separate class for each version. This was partially done for the keystoneclient in api/keystone.py, but not for the forms/views, where we still have if-else for versions. What I suggest here is to have different(concrete) views/forms for each version, and to use them according the context. If the Keystone backend is v2.0 - then in the Frontend use keystone2() object, otherwise use keystone3() object. This of course needs some more coding, but is much cleaner in terms of customization and testing. For me the current hacks with 'if keystone.version == 3.0' are wrong at many levels. And this can be solved now. <b>The problem till now was that we had one frontend that had to be backed by different versions of backend components</b>. <b>Now we can have different frontends that map to specific backend</b>. That's how I understand the power of Angular with it's views and directives. That's where I see the real benefit of using full-featured frontend. Also imagine how easy will be then to deprecate a component version, compared to what we need to do now for the same.</div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif"><br></div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif">Otherwise we just rewrite the current Django middleware with another DjangoRest middleware and don't change anything, we don't fix the problems. We just move them to another place.</div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif"><br></div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif">I still think that in Paris we talked about a new generation of the Dashboard, a different approach on building the frontend for OpenStack. What I've heard there from users/operators of Horizon was that it was extremely hard to add customizations and new features to the Dashboard, as all these needed to go through upstream changes and to wait until next release cycle to get them. Do we still want to address these concerns and how? Please, correct me if I got things wrong.</div><div class="gmail_default" style="font-family:trebuchet ms,sans-serif"><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Dec 10, 2014 at 11:56 AM, Richard Jones <span dir="ltr"><<a href="mailto:r1chardj0n3s@gmail.com" target="_blank">r1chardj0n3s@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Sorry I didn't respond to this earlier today, I had intended to.<div><br></div><div>What you're describing isn't REST, and the principles of REST are what have been guiding the design of the new API so far. I see a lot of value in using REST approaches, mostly around clarity of the interface.</div><div><br></div><div><span style="line-height:19.7999992370605px">While the idea of a very thin proxy seemed like a great idea at one point, my conversations at the summit convinced me that there was value in both using the client interfaces present in the openstack_dashboard/api code base (since they abstract away many issues in the apis including across versions) and also value in us being able to clean up (for example, using "project_id" rather than "project" in the user API we've already implemented) and extend those interfaces (to allow batched operations).</span><br></div><div><span style="line-height:1.5"><br></span></div><div><span style="line-height:1.5">We want to be careful about what we expose in Horizon to the JS clients through this API. That necessitates some amount of code in Horizon. About half of the current API for keysone represents that control (the other half is docstrings :)</span></div><span class="HOEnZb"><font color="#888888"><div><br><div><br></div><div>     Richard</div><div><br></div></div><br></font></span><div class="gmail_quote"><div><div class="h5">On Tue Dec 09 2014 at 9:37:47 PM Tihomir Trifonov <<a href="mailto:t.trifonov@gmail.com" target="_blank">t.trifonov@gmail.com</a>> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5"><div dir="ltr"><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif">Sorry for the late reply, just few thoughts on the matter.</div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif"><br></div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif">IMO the REST middleware should be as thin as possible. And I mean thin in terms of processing - it should not do pre/post processing of the requests, but just unpack/pack. So here is an example:</div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif"><br></div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif">instead of making AJAX calls that contain instructions:</div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif"><br></div><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex" class="gmail_quote"><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​​</div>POST --json --data {"action": "delete", "data": [ {"name": "item1"}, {"name": "item2"}, {"name": "item3" ]}</blockquote><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif"><br></div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif">I think a better approach is just to pack/unpack batch commands, and leave execution to the frontend/backend and not middleware:</div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif"><br></div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif"><br></div><blockquote style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex" class="gmail_quote"><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​​</div>POST --json --data {"<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​batch</div>": <div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​[ </div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">{​</div>"<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​</div><span style="font-family:'trebuchet ms',sans-serif">action</span>"<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​ : "delete"​</div>, <div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​"payload": ​</div>{"name": "item1"}<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​, </div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">{​</div>"<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​</div><span style="font-family:'trebuchet ms',sans-serif">action</span>"<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​ : "delete"​</div>, <div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​</div><span style="font-family:'trebuchet ms',sans-serif">"payload":</span><span style="font-family:'trebuchet ms',sans-serif"> </span><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​</div>{"name": "item<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​2</div>"}<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​, </div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">{​</div>"<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​</div><span style="font-family:'trebuchet ms',sans-serif">action</span>"<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​ : "delete"​</div>, <div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​</div><span style="font-family:'trebuchet ms',sans-serif">"payload":</span><span style="font-family:'trebuchet ms',sans-serif"> </span><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​</div>{"name": "item<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​3</div>"}<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​ ] ​</div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​</div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​</div>}</blockquote><div><br></div><div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​The idea is that the middleware should not know the actual data. It should ideally just unpack the data:</div></div><div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline"><br></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​​responses = []</div> </blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">for cmd in<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​ ​</div>​<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​</div><span style="font-family:'trebuchet ms',sans-serif">request.POST['batch']:</span><span style="font-family:'trebuchet ms',sans-serif">​</span></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">    <div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​</div><span style="font-family:'trebuchet ms',sans-serif">​​responses<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​.append(​</div></span><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​</div>getattr(controller, cmd['action']<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​)(**</div>cmd['​payload']<div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​)​)</div></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> <div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​return responses​</div></blockquote><div><br></div><div><br></div><div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​and the frontend(JS) will just send batches of simple commands, and will receive a list of responses for each command in the batch. The error handling will be done in the frontend​(JS) as well.</div></div> <div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline">​</div><div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif;display:inline"><br></div></div>For the more complex example of 'put()' where we have dependent objects:<div><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">project = api.keystone.tenant_get(request, id)<br>kwargs = self._tenant_kwargs_from_DATA(request.DATA, enabled=None)<br>api.keystone.tenant_update(request, project, **kwargs)</blockquote><div><br></div><div><br></div><div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif">In practice the project data should be already present in the frontend(assuming that we already loaded it to render the project form/view), so </div><br></div><div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif">​<div class="gmail_default" style="display:inline">​</div><span style="font-family:arial,sans-serif">POST --json --data {"</span><div class="gmail_default" style="display:inline">​batch</div><span style="font-family:arial,sans-serif">":</span><span style="font-family:arial,sans-serif"> </span><div class="gmail_default" style="display:inline">​[ </div><div class="gmail_default" style="display:inline">{​</div><span style="font-family:arial,sans-serif">"</span><div class="gmail_default" style="display:inline">​</div>action<span style="font-family:arial,sans-serif">"</span><div class="gmail_default" style="display:inline">​ : "tenant_update"​</div><span style="font-family:arial,sans-serif">,</span><span style="font-family:arial,sans-serif"> </span><div class="gmail_default" style="display:inline">​"payload": ​</div><span style="font-family:arial,sans-serif">{"project": <a href="http://js_project_object.id" target="_blank">js_project_object.id</a>, "name": "some name", "prop1": "some prop", "prop2": "other prop, etc."}</span><div class="gmail_default" style="display:inline">​</div><div class="gmail_default" style="display:inline">​ ] ​</div><div class="gmail_default" style="display:inline">​</div><div class="gmail_default" style="display:inline">​</div><span style="font-family:arial,sans-serif">}</span>​</div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif"><br></div><div class="gmail_default" style="font-family:'trebuchet ms',sans-serif">So in general we don't need to recreate the full state on each REST call, if we make the Frontent full-featured application. This way - the frontend will construct the object, will hold the cached value, and will just send the needed requests as single ones or in batches, will receive the response from the API backend, and will render the results. The whole processing logic will be held in the Frontend(JS), while the middleware will just act as proxy(un/packer). This way we will maintain just the logic in the frontend, and will not need to duplicate some logic in the middleware.</div><br></div><div><br></div><div> </div></div></div><div class="gmail_extra"></div></div></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Tue, Dec 2, 2014 at 4:45 PM, Adam Young <span dir="ltr"><<a href="mailto:ayoung@redhat.com" target="_blank">ayoung@redhat.com</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">              <div bgcolor="#FFFFFF" text="#000000"><div><div class="h5"><span>     <div>On 12/02/2014 12:39 AM, Richard Jones       wrote:<br>     </div>     <blockquote type="cite">       <div class="gmail_quote">On Mon Dec 01 2014 at 4:18:42 PM Thai Q         Tran <<a href="mailto:tqtran@us.ibm.com" target="_blank">tqtran@us.ibm.com</a>>         wrote:<br>         <blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">           <div>             <p><font face="sans-serif">I agree that keeping the API                 layer thin would be ideal. I should add that having                 discrete API calls would allow dynamic population of                 table. However, I will make a case where it </font><font face="sans-serif"><b><i>might</i></b></font><font face="sans-serif"> be necessary to add additional APIs.                 Consider that you want to delete 3 items in a given                 table. </font><br>               <br>               <font face="sans-serif">If you do this on the client side,                 you would need to perform: n * (1 API request + 1 AJAX                 request)</font><br>               <font face="sans-serif">If you have some logic on the                 server side that batch delete actions: n * (1 API                 request) + 1 AJAX request</font><br>               <br>               <font face="sans-serif">Consider the following:</font><br>               <font face="sans-serif">n = 1, client = 2 trips, server =                 2 trips</font><br>               <font face="sans-serif">n = 3, client = 6 trips, server =                 4 trips</font><br>               <font face="sans-serif">n = 10, client = 20 trips, server                 = 11 trips</font><br>               <font face="sans-serif">n = 100, client = 200 trips,                 server 101 trips</font><br>               <br>               <font face="sans-serif">As you can see, this does not                 scale very well.... something to consider...</font></p>           </div>         </blockquote>       </div>     </blockquote></span>     This is not something Horizon can fix.  Horizon can make matters     worse, but cannot make things better.<br>     <br>     If you want to delete 3 users,   Horizon still needs to make 3     distinct calls to Keystone.<br>     <br>     To fix this, we need either batch calls or a standard way to do     multiples of the same operation.<br>     <br>     The unified API effort it the right place to drive this.</div></div><div><div><br>     <br>     <br>     <br>     <br>     <br>     <br>     <blockquote type="cite"><div><div class="h5">       <div class="gmail_quote">         <div>Yep, though in the above cases the client is still going to           be hanging, waiting for those server-backend calls, with no           feedback until it's all done. I would hope that the           client-server call overhead is minimal, but I guess that's           probably wishful thinking when in the land of random Internet           users hitting some provider's Horizon :)</div>         <div><br>         </div>         <div>So yeah, having mulled it over myself I agree that it's           useful to have batch operations implemented in the POST           handler, the most common operation being DELETE.</div>         <div><br>         </div>         <div>Maybe one day we could transition to a batch call with user           feedback using a websocket connection.</div>       </div>       <div class="gmail_quote">         <div><br>         </div>         <div><br>         </div>         <div>     Richard</div>       </div>       </div></div><div><div class="h5"><div class="gmail_quote">         <blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">           <div>             <p></p><img src="cid:994faa67a8e28335_0.0.1.1" style="max-width:100%" ><font color="#424282" face="sans-serif">Richard Jones ---11/27/2014 05:38:53                 PM---On Fri Nov 28 2014 at 5:58:00 AM Tripp, Travis S                 <<a href="mailto:travis.tripp@hp.com" target="_blank">travis.tripp@hp.com</a>>                 wrote:</font><br>               <br>               <font color="#5F5F5F" face="sans-serif" size="1">From: </font><font face="sans-serif" size="1">Richard Jones <<a href="mailto:r1chardj0n3s@gmail.com" target="_blank">r1chardj0n3s@gmail.com</a>></font><br>               <font color="#5F5F5F" face="sans-serif" size="1">To: </font><font face="sans-serif" size="1">"Tripp, Travis S" <<a href="mailto:travis.tripp@hp.com" target="_blank">travis.tripp@hp.com</a>>,                 OpenStack List <<a href="mailto:openstack-dev@lists.openstack.org" target="_blank">openstack-dev@lists.openstack.org</a>></font><br>               <font color="#5F5F5F" face="sans-serif" size="1">Date: </font><font face="sans-serif" size="1">11/27/2014 05:38 PM</font><br>               <font color="#5F5F5F" face="sans-serif" size="1">Subject:               </font><font face="sans-serif" size="1">Re:                 [openstack-dev] [horizon] REST and Django</font><br>             <p></p>             <hr align="left" size="2" width="100%"></div>           <div>             <p><br>               <br>               <br>               <font face="serif" size="3">On Fri Nov 28 2014 at 5:58:00                 AM Tripp, Travis S <</font><a href="mailto:travis.tripp@hp.com" target="_blank"><font color="#0000FF" face="serif" size="3"><u>travis.tripp@hp.com</u></font></a><font face="serif" size="3">> wrote:</font>             </p>             <ul style="padding-left:9pt">               <font face="Calibri" size="1">Hi Richard,</font><br>               <br>               <font face="Calibri" size="1">You are right, we should put                 this out on the main ML, so copying thread out to                 there.  ML: FYI that this started after some impromptu                 IRC discussions about a specific patch led into an                 impromptu google hangout discussion with all the people                 on the thread below.</font>             </ul>             <br>             <font face="serif" size="3">Thanks Travis!</font><br>             <br>             <font face="serif" size="3"> </font>             <ul style="padding-left:9pt">               <font face="Calibri" size="1">As I mentioned in the                 review[1], Thai and I were mainly discussing the                 possible performance implications of network hops from                 client to horizon server and whether or not any                 aggregation should occur server side.   In other words,                 some views  require several APIs to be queried before                 any data can displayed and it would eliminate some extra                 network requests from client to server if some of the                 data was first collected on the server side across                 service APIs.  For example, the launch instance wizard                 will need to collect data from quite a few APIs before                 even the first step is displayed (I’ve listed those out                 in the blueprint [2]).</font><br>               <br>               <font face="Calibri" size="1">The flip side to that (as                 you also pointed out) is that if we keep the API’s fine                 grained then the wizard will be able to optimize in one                 place the calls for data as it is needed. For example,                 the first step may only need half of the API calls. It                 also could lead to perceived performance increases just                 due to the wizard making a call for different data                 independently and displaying it as soon as it can.</font>             </ul>             <br>             <font face="serif" size="3">Indeed, looking at the current               launch wizard code it seems like you wouldn't need to load               all that data for the wizard to be displayed, since only               some subset of it would be necessary to display any given               panel of the wizard. </font><br>             <br>             <font face="serif" size="3"> </font>             <ul style="padding-left:9pt">               <font face="Calibri" size="1">I tend to lean towards your                 POV and starting with discrete API calls and letting the                 client optimize calls.  If there are performance                 problems or other reasons then doing data aggregation on                 the server side could be considered at that point.</font>             </ul>             <br>             <font face="serif" size="3">I'm glad to hear it. I'm a fan               of optimising when necessary, and not beforehand :)</font><br>             <br>             <font face="serif" size="3"> </font>             <ul style="padding-left:9pt">               <font face="Calibri" size="1">Of course if anybody is able                 to do some performance testing between the two                 approaches then that could affect the direction taken.</font>             </ul>             <br>             <font face="serif" size="3">I would certainly like to see us               take some measurements when performance issues pop up.               Optimising without solid metrics is bad idea :)</font><br>             <br>             <br>             <font face="serif" size="3">    Richard</font><br>             <font face="serif" size="3"> </font>           </div>           <div>             <ul style="padding-left:9pt">               <br>               <font face="Calibri" size="1">[1] </font><a href="https://review.openstack.org/#/c/136676/8/openstack_dashboard/api/rest/urls.py" target="_blank"><font color="#0000FF" face="Calibri" size="1"><u>https://review.openstack.org/#/c/136676/8/openstack_dashboard/api/rest/urls.py</u></font></a><br>               <font face="Calibri" size="1">[2] </font><a href="https://blueprints.launchpad.net/horizon/+spec/launch-instance-redesign" target="_blank"><font color="#0000FF" face="Calibri" size="1"><u>https://blueprints.launchpad.net/horizon/+spec/launch-instance-redesign</u></font></a><br>               <br>               <font face="Calibri" size="1">-Travis</font><br>               <br>               <font face="Calibri"><b>From: </b></font><font face="Calibri">Richard Jones <</font><a href="mailto:r1chardj0n3s@gmail.com" target="_blank"><font color="#0000FF" face="Calibri"><u>r1chardj0n3s@gmail.com</u></font></a><font face="Calibri">></font><font face="Calibri"><b><br>                   Date: </b></font><font face="Calibri">Wednesday,                 November 26, 2014 at 11:55 PM</font><font face="Calibri"><b><br>                   To: </b></font><font face="Calibri">Travis Tripp <</font><a href="mailto:travis.tripp@hp.com" target="_blank"><font color="#0000FF" face="Calibri"><u>travis.tripp@hp.com</u></font></a><font face="Calibri">>, Thai Q Tran/Silicon Valley/IBM <</font><a href="mailto:tqtran@us.ibm.com" target="_blank"><font color="#0000FF" face="Calibri"><u>tqtran@us.ibm.com</u></font></a><font face="Calibri">>, David Lyle <</font><a href="mailto:dklyle0@gmail.com" target="_blank"><font color="#0000FF" face="Calibri"><u>dklyle0@gmail.com</u></font></a><font face="Calibri">>, Maxime Vidori <</font><a href="mailto:maxime.vidori@enovance.com" target="_blank"><font color="#0000FF" face="Calibri"><u>maxime.vidori@enovance.com</u></font></a><font face="Calibri">>, "Wroblewski, Szymon" <</font><a href="mailto:szymon.wroblewski@intel.com" target="_blank"><font color="#0000FF" face="Calibri"><u>szymon.wroblewski@intel.com</u></font></a><font face="Calibri">>, "Wood, Matthew David (HP Cloud -                 Horizon)" <</font><a href="mailto:matt.wood@hp.com" target="_blank"><font color="#0000FF" face="Calibri"><u>matt.wood@hp.com</u></font></a><font face="Calibri">>, "Chen, Shaoquan" <</font><a href="mailto:sean.chen2@hp.com" target="_blank"><font color="#0000FF" face="Calibri"><u>sean.chen2@hp.com</u></font></a><font face="Calibri">>, "Farina, Matt (HP Cloud)" <</font><a href="mailto:matthew.farina@hp.com" target="_blank"><font color="#0000FF" face="Calibri"><u>matthew.farina@hp.com</u></font></a><font face="Calibri">>, Cindy Lu/Silicon Valley/IBM <</font><a href="mailto:clu@us.ibm.com" target="_blank"><font color="#0000FF" face="Calibri"><u>clu@us.ibm.com</u></font></a><font face="Calibri">>, Justin Pomeroy/Rochester/IBM <</font><a href="mailto:jpomero@us.ibm.com" target="_blank"><font color="#0000FF" face="Calibri"><u>jpomero@us.ibm.com</u></font></a><font face="Calibri">>, Neill Cox <</font><a href="mailto:neill.cox@ingenious.com.au" target="_blank"><font color="#0000FF" face="Calibri"><u>neill.cox@ingenious.com.au</u></font></a><font face="Calibri">></font><font face="Calibri"><b><br>                   Subject: </b></font><font face="Calibri">Re: REST and                 Django</font><br>               <br>               <font face="Calibri" size="1">I'm not sure whether this is                 the appropriate place to discuss this, or whether I                 should be posting to the list under [Horizon] but I                 think we need to have a clear idea of what goes in the                 REST API and what goes in the client (angular) code.</font><br>               <br>               <font face="Calibri" size="1">In my mind, the thinner the                 REST API the better. Indeed if we can get away with                 proxying requests through without touching any *client                 code, that would be great.</font><br>               <br>               <font face="Calibri" size="1">Coding additional logic into                 the REST API means that a developer would need to look                 in two places, instead of one, to determine what was                 happening for a particular call. If we keep it thin then                 the API presented to the client developer is very, very                 similar to the API presented by the services. Minimum                 surprise.</font><br>               <br>               <font face="Calibri" size="1">Your thoughts?</font><br>               <br>               <br>               <font face="Calibri" size="1">     Richard</font><br>               <br>               <br>               <font face="Calibri" size="1">On Wed Nov 26 2014 at                 2:40:52 PM Richard Jones <</font><a href="mailto:r1chardj0n3s@gmail.com" target="_blank"><font color="#0000FF" face="Calibri" size="1"><u>r1chardj0n3s@gmail.com</u></font></a><font face="Calibri" size="1">> wrote:</font>             </ul>           </div>           <div>             <ul style="padding-left:9pt">               <ul style="padding-left:9pt">                 <font face="Calibri" size="1">Thanks for the great                   summary, Travis. </font><br>                 <br>                 <font face="Calibri" size="1">I've completed the work I                   pledged this morning, so now the REST API change set                   has:</font><br>                 <br>                 <font face="Calibri" size="1">- no rest framework                   dependency</font><br>                 <font face="Calibri" size="1">- AJAX scaffolding in                   openstack_dashboard.api.rest.utils</font><br>                 <font face="Calibri" size="1">- code in                   openstack_dashboard/api/rest/</font><br>                 <font face="Calibri" size="1">- renamed the API from                   "identity" to "keystone" to be consistent</font><br>                 <font face="Calibri" size="1">- added a sample of                   testing, mostly for my own sanity to check things were                   working</font><br>                 <br>                 <a href="https://review.openstack.org/#/c/136676" target="_blank"><font color="#0000FF" face="Calibri" size="1"><u>https://review.openstack.org/#/c/136676</u></font></a><br>                 <br>                 <br>                 <font face="Calibri" size="1">      Richard</font><br>                 <br>                 <font face="Calibri" size="1">On Wed Nov 26 2014 at                   12:18:25 PM Tripp, Travis S <</font><a href="mailto:travis.tripp@hp.com" target="_blank"><font color="#0000FF" face="Calibri" size="1"><u>travis.tripp@hp.com</u></font></a><font face="Calibri" size="1">> wrote:</font>               </ul>             </ul>           </div>           <div>             <ul style="padding-left:9pt">               <ul style="padding-left:9pt">                 <ul style="padding-left:9pt">                   <font face="Calibri" size="1">Hello all,</font><br>                   <br>                   <font face="Calibri" size="1">Great discussion on the                     REST urls today! I think that we are on track to                     come to a common REST API usage pattern.  To provide                     quick summary:</font><br>                   <br>                   <font face="Calibri" size="1">We all agreed that going                     to a straight REST pattern rather than through                     tables was a good idea. We discussed using direct                     get / post in Django views like what Max originally                     used[1][2] and Thai also started[3] with the                     identity table rework or to go with                     djangorestframework [5] like what Richard was                     prototyping with[4].</font><br>                   <br>                   <font face="Calibri" size="1">The main things we would                     use from Django Rest Framework were built in JSON                     serialization (avoid boilerplate), better exception                     handling, and some request wrapping.  However, we                     all weren’t sure about the need for a full new                     framework just for that. At the end of the                     conversation, we decided that it was a cleaner                     approach, but Richard would see if he could provide                     some utility code to do that much for us without                     requiring the full framework.  David voiced that he                     doesn’t want us building out a whole framework on                     our own either.</font><br>                   <br>                   <font face="Calibri" size="1">So, Richard will do some                     investigation during his day today and get back to                     us.  Whatever the case, we’ll get a patch in horizon                     for the base dependency (framework or Richard’s                     utilities) that both Thai’s work and the launch                     instance work is dependent upon.  We’ll build REST                     style API’s using the same pattern.  We will likely                     put the rest api’s in horizon/openstack_dashboard/api/rest/.</font><br>                   <br>                   <font face="Calibri" size="1">[1] </font><a href="https://review.openstack.org/#/c/133178/1/openstack_dashboard/workflow/keypair.py" target="_blank"><font color="#0000FF" face="Calibri" size="1"><u>https://review.openstack.org/#/c/133178/1/openstack_dashboard/workflow/keypair.py</u></font></a><br>                   <font face="Calibri" size="1">[2] </font><a href="https://review.openstack.org/#/c/133178/1/openstack_dashboard/workflow/launch.py" target="_blank"><font color="#0000FF" face="Calibri" size="1"><u>https://review.openstack.org/#/c/133178/1/openstack_dashboard/workflow/launch.py</u></font></a><br>                   <font face="Calibri" size="1">[3] </font><a href="https://review.openstack.org/#/c/133767/8/openstack_dashboard/dashboards/identity/users/views.py" target="_blank"><font color="#0000FF" face="Calibri" size="1"><u>https://review.openstack.org/#/c/133767/8/openstack_dashboard/dashboards/identity/users/views.py</u></font></a><br>                   <font face="Calibri" size="1">[4] </font><a href="https://review.openstack.org/#/c/136676/4/openstack_dashboard/rest_api/identity.py" target="_blank"><font color="#0000FF" face="Calibri" size="1"><u>https://review.openstack.org/#/c/136676/4/openstack_dashboard/rest_api/identity.py</u></font></a><br>                   <font face="Calibri" size="1">[5] </font><a href="http://www.django-rest-framework.org/" target="_blank"><font color="#0000FF" face="Calibri" size="1"><u>http://www.django-rest-framework.org/</u></font></a><br>                   <br>                   <font face="Calibri" size="1">Thanks,</font><br>                 </ul>               </ul>             </ul>           </div>           <div>             <ul style="padding-left:9pt">               <ul style="padding-left:9pt">                 <ul style="padding-left:9pt">                   <font face="Calibri" size="1">Travis</font><tt><font face="Courier New,Courier,monospace" size="3">_______________________________________________<br>                       OpenStack-dev mailing list<br>                       <a href="mailto:OpenStack-dev@lists.openstack.org" target="_blank">OpenStack-dev@lists.openstack.org</a><br>                     </font></tt><tt><font face="Courier New,Courier,monospace" size="3"><a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a></font></tt><tt><font face="Courier New,Courier,monospace" size="3"><br>                     </font></tt><br>                 </ul>               </ul>             </ul>           </div>           _______________________________________________<br>           OpenStack-dev mailing list<br>           <a href="mailto:OpenStack-dev@lists.openstack.org" target="_blank">OpenStack-dev@lists.openstack.org</a><br>           <a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>         </blockquote>       </div>       <br>       <fieldset></fieldset>       <br>       <div><font face="Courier New,Courier,monospace" size="3">_______________________________________________<br>OpenStack-dev mailing list<br><a href="mailto:OpenStack-dev@lists.openstack.org" target="_blank">OpenStack-dev@lists.openstack.org</a><br><a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br></font></div>     </div></div></blockquote>     <br>   </div></div></div><div><div class="h5"> <br>_______________________________________________<br> OpenStack-dev mailing list<br> <a href="mailto:OpenStack-dev@lists.openstack.org" target="_blank">OpenStack-dev@lists.openstack.org</a><br> <a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br> <br></div></div></blockquote></div><br><br clear="all"><div><br></div></div><div><div class="h5"><div class="gmail_extra">-- <br><div>Regards,<br>Tihomir Trifonov</div> </div> ______________________________<u></u>_________________<br> OpenStack-dev mailing list<br> <a href="mailto:OpenStack-dev@lists.openstack.org" target="_blank">OpenStack-dev@lists.openstack.<u></u>org</a><br> <a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/<u></u>cgi-bin/mailman/listinfo/<u></u>openstack-dev</a><br> </div></div></blockquote></div> <br>_______________________________________________<br> OpenStack-dev mailing list<br> <a href="mailto:OpenStack-dev@lists.openstack.org">OpenStack-dev@lists.openstack.org</a><br> <a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br> <br></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature">Regards,<br>Tihomir Trifonov</div> </div> <div><font face="Courier New,Courier,monospace" size="3">_______________________________________________<br>OpenStack-dev mailing list<br>OpenStack-dev@lists.openstack.org<br><a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br></font></div></div></div></font>