<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On 21 January 2016 at 14:46, Dougal Matthews <span dir="ltr"><<a href="mailto:dougal@redhat.com" target="_blank">dougal@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On 20 January 2016 at 20:05, Tzu-Mainn Chen <span dir="ltr"><<a href="mailto:tzumainn@redhat.com" target="_blank">tzumainn@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div>----- Original Message -----<br>
> On 18.1.2016 19:49, Tzu-Mainn Chen wrote:<br>
> > ----- Original Message -----<br>
> >> On Thu, 2016-01-14 at 16:04 -0500, Tzu-Mainn Chen wrote:<br>
> >>><br>
> >>> ----- Original Message -----<br>
> >>>> On Wed, Jan 13, 2016 at 04:41:28AM -0500, Tzu-Mainn Chen wrote:<br>
> >>>>> Hey all,<br>
> >>>>><br>
> >>>>> I realize now from the title of the other TripleO/Mistral thread<br>
> >>>>> [1] that<br>
> >>>>> the discussion there may have gotten confused. I think using<br>
> >>>>> Mistral for<br>
> >>>>> TripleO processes that are obviously workflows - stack<br>
> >>>>> deployment, node<br>
> >>>>> registration - makes perfect sense. That thread is exploring<br>
> >>>>> practicalities<br>
> >>>>> for doing that, and I think that's great work.<br>
> >>>>><br>
> >>>>> What I inappropriately started to address in that thread was a<br>
> >>>>> somewhat<br>
> >>>>> orthogonal point that Dan asked in his original email, namely:<br>
> >>>>><br>
> >>>>> "what it might look like if we were to use Mistral as a<br>
> >>>>> replacement for the<br>
> >>>>> TripleO API entirely"<br>
> >>>>><br>
> >>>>> I'd like to create this thread to talk about that; more of a<br>
> >>>>> 'should we'<br>
> >>>>> than 'can we'. And to do that, I want to indulge in a thought<br>
> >>>>> exercise<br>
> >>>>> stemming from an IRC discussion with Dan and others. All, please<br>
> >>>>> correct<br>
> >>>>> me<br>
> >>>>> if I've misstated anything.<br>
> >>>>><br>
> >>>>> The IRC discussion revolved around one use case: deploying a Heat<br>
> >>>>> stack<br>
> >>>>> directly from a Swift container. With an updated patch, the Heat<br>
> >>>>> CLI can<br>
> >>>>> support this functionality natively. Then we don't need a<br>
> >>>>> TripleO API; we<br>
> >>>>> can use Mistral to access that functionality, and we're done,<br>
> >>>>> with no need<br>
> >>>>> for additional code within TripleO. And, as I understand it,<br>
> >>>>> that's the<br>
> >>>>> true motivation for using Mistral instead of a TripleO API:<br>
> >>>>> avoiding custom<br>
> >>>>> code within TripleO.<br>
> >>>>><br>
> >>>>> That's definitely a worthy goal... except from my perspective,<br>
> >>>>> the story<br>
> >>>>> doesn't quite end there. A GUI needs additional functionality,<br>
> >>>>> which boils<br>
> >>>>> down to: understanding the Heat deployment templates in order to<br>
> >>>>> provide<br>
> >>>>> options for a user; and persisting those options within a Heat<br>
> >>>>> environment<br>
> >>>>> file.<br>
> >>>>><br>
> >>>>> Right away I think we hit a problem. Where does the code for<br>
> >>>>> 'understanding<br>
> >>>>> options' go? Much of that understanding comes from the<br>
> >>>>> capabilities map<br>
> >>>>> in tripleo-heat-templates [2]; it would make sense to me that<br>
> >>>>> responsibility<br>
> >>>>> for that would fall to a TripleO library.<br>
> >>>>><br>
> >>>>> Still, perhaps we can limit the amount of TripleO code. So to<br>
> >>>>> give API<br>
> >>>>> access to 'getDeploymentOptions', we can create a Mistral<br>
> >>>>> workflow.<br>
> >>>>><br>
> >>>>> Retrieve Heat templates from Swift -> Parse capabilities map<br>
> >>>>><br>
> >>>>> Which is fine-ish, except from an architectural perspective<br>
> >>>>> 'getDeploymentOptions' violates the abstraction layer between<br>
> >>>>> storage and<br>
> >>>>> business logic, a problem that is compounded because<br>
> >>>>> 'getDeploymentOptions'<br>
> >>>>> is not the only functionality that accesses the Heat templates<br>
> >>>>> and needs<br>
> >>>>> exposure through an API. And, as has been discussed on a<br>
> >>>>> separate TripleO<br>
> >>>>> thread, we're not even sure Swift is sufficient for our needs;<br>
> >>>>> one possible<br>
> >>>>> consideration right now is allowing deployment from templates<br>
> >>>>> stored in<br>
> >>>>> multiple places, such as the file system or git.<br>
> >>>><br>
> >>>> Actually, that whole capabilities map thing is a workaround for a<br>
> >>>> missing<br>
> >>>> feature in Heat, which I have proposed, but am having a hard time<br>
> >>>> reaching<br>
> >>>> consensus on within the Heat community:<br>
> >>>><br>
> >>>> <a href="https://review.openstack.org/#/c/196656/" rel="noreferrer" target="_blank">https://review.openstack.org/#/c/196656/</a><br>
> >>>><br>
> >>>> Given that is a large part of what's anticipated to be provided by<br>
> >>>> the<br>
> >>>> proposed TripleO API, I'd welcome feedback and collaboration so we<br>
> >>>> can move<br>
> >>>> that forward, vs solving only for TripleO.<br>
> >>>><br>
> >>>>> Are we going to have duplicate 'getDeploymentOptions' workflows<br>
> >>>>> for each<br>
> >>>>> storage mechanism? If we consolidate the storage code within a<br>
> >>>>> TripleO<br>
> >>>>> library, do we really need a *workflow* to call a single<br>
> >>>>> function? Is a<br>
> >>>>> thin TripleO API that contains no additional business logic<br>
> >>>>> really so bad<br>
> >>>>> at that point?<br>
> >>>><br>
> >>>> Actually, this is an argument for making the validation part of the<br>
> >>>> deployment a workflow - then the interface with the storage<br>
> >>>> mechanism<br>
> >>>> becomes more easily pluggable vs baked into an opaque-to-operators<br>
> >>>> API.<br>
> >>>><br>
> >>>> E.g, in the long term, imagine the capabilities feature exists in<br>
> >>>> Heat, you<br>
> >>>> then have a pre-deployment workflow that looks something like:<br>
> >>>><br>
> >>>> 1. Retrieve golden templates from a template store<br>
> >>>> 2. Pass templates to Heat, get capabilities map which defines<br>
> >>>> features user<br>
> >>>> must/may select.<br>
> >>>> 3. Prompt user for input to select required capabilites<br>
> >>>> 4. Pass user input to Heat, validate the configuration, get a<br>
> >>>> mapping of<br>
> >>>> required options for the selected capabilities (nested validation)<br>
> >>>> 5. Push the validated pieces ("plan" in TripleO API terminology) to<br>
> >>>> a<br>
> >>>> template store<br>
> >>>><br>
> >>>> This is a pre-deployment validation workflow, and it's a superset<br>
> >>>> of the<br>
> >>>> getDeploymentOptions feature you refer to.<br>
> >>>><br>
> >>>> Historically, TripleO has had a major gap wrt workflow, meaning<br>
> >>>> that we've<br>
> >>>> always implemented it either via shell scripts (tripleo-incubator)<br>
> >>>> or<br>
> >>>> python code (tripleo-common/tripleo-client, potentially TripleO<br>
> >>>> API).<br>
> >>>><br>
> >>>> So I think what Dan is exploring is, how do we avoid reimplementing<br>
> >>>> a<br>
> >>>> workflow engine, when a project exists which already does that.<br>
> >>>><br>
> >>>>> My gut reaction is to say that proposing Mistral in place of a<br>
> >>>>> TripleO API<br>
> >>>>> is to look at the engineering concerns from the wrong<br>
> >>>>> direction. The<br>
> >>>>> Mistral alternative comes from a desire to limit custom TripleO<br>
> >>>>> code at all<br>
> >>>>> costs. I think that is an extremely dangerous attitude that<br>
> >>>>> leads to<br>
> >>>>> compromises and workarounds that will quickly lead to a shaky<br>
> >>>>> code base<br>
> >>>>> full of design flaws that make it difficult to implement or<br>
> >>>>> extend any<br>
> >>>>> functionality cleanly.<br>
> >>>><br>
> >>>> I think it's not about limiting TripleO code at all costs, it's<br>
> >>>> about<br>
> >>>> learning from past mistakes, where long-term TripleO specific<br>
> >>>> workarounds<br>
> >>>> for gaps in other projects have become serious technical debt.<br>
> >>>><br>
> >>>> For example, the old merge.py approach to template composition was<br>
> >>>> a<br>
> >>>> workaround for missing heat features, then Tuskar was another<br>
> >>>> workaround<br>
> >>>> (arguably) for missing heat features, and now we're again proposing<br>
> >>>> a<br>
> >>>> long-term workaround for some missing heat features, some of which<br>
> >>>> are<br>
> >>>> already proposed (referring to the API for capabilities<br>
> >>>> resolution).<br>
> >>>><br>
> >>><br>
> >>> This is an important point, thanks for bringing it up!<br>
> >>><br>
> >>> I think that I might have a different understanding of the lessons to<br>
> >>> be<br>
> >>> learned from Tuskar's limitations. There were actually two issues<br>
> >>> that<br>
> >>> arose. The first was that Tuskar was far too specific in how it<br>
> >>> tried to<br>
> >>> manipulated Heat pieces. The second - and more serious, from my<br>
> >>> point of<br>
> >>> view - was that there literally was no way for an API-based GUI to<br>
> >>> perform the tasks it needed to in order to do the correct<br>
> >>> manipulation<br>
> >>> (environment selection), because there was no Heat API in place for<br>
> >>> doing<br>
> >>> so.<br>
> >>><br>
> >>> My takeaway from the first issue was that any potential TripleO API<br>
> >>> in<br>
> >>> the future needed to be very low-level, a light skimming on top of<br>
> >>> the<br>
> >>> OpenStack services it uses. The plan creation process that the<br>
> >>> tripleo-common library spec describes is that: it's just a couple of<br>
> >>> methods designed to allow a user to create an environment file, which<br>
> >>> can then be used for deploying the overcloud.<br>
> >>><br>
> >>> My takeaway from the second issue was a bit more complicated. A<br>
> >>> required feature was missing, and although the proper functionality<br>
> >>> needed to enable it in Heat was identified, it was unclear (and<br>
> >>> remains<br>
> >>> unclear) whether that feature truly belonged in Heat. What does a<br>
> >>> GUI<br>
> >>> do then? The GUI could take a cycle off, which is essentially what<br>
> >>> happened here; I don't think that's a reasonable solution. We could<br>
> >>> hope that we arrive at a 100% foolproof and immutable deployment<br>
> >>> solution<br>
> >>> in the future, arriving at a point where no new features would ever<br>
> >>> be<br>
> >>> needed; I don't think that's a practical hope.<br>
> >>><br>
> >>> The third solution that came to mind was the idea of creating the<br>
> >>> TripleO API. It gives us a place to add in missing features if<br>
> >>> needed.<br>
> >>> And I think it also gives us a useful layer of indirection. The<br>
> >>> consumers of TripleO want a stable API, so that a new release doesn't<br>
> >>> force them to do a massive update of their code; the TripleO API<br>
> >>> would<br>
> >>> provide that, allowing us to switch code behind the scenes (say, if<br>
> >>> the capabilities feature lands in Heat).<br>
> >><br>
> >> I think the above example would work equally well in a generic workflow<br>
> >> sort of tool. You could image that the inputs to the workflow remain<br>
> >> the same... but rather than running our own code in some interim step<br>
> >> we simply call Heat directly for the capabilities map feature.<br>
> >><br>
> >> So regardless of whether we build our own API or use a generic workflow<br>
> >> too I think we still have what I would call a "release valve" to let us<br>
> >> inject some custom code (actions) into the workflow. Like we discussed<br>
> >> last week on IRC I would like to minimize the number of custom actions<br>
> >> we have (with an eye towards things living in the upstream OpenStack<br>
> >> projects) but it is fine to do this either way and would work equally<br>
> >> well w/ Mistral and TripleO API.<br>
> >><br>
> >>><br>
> >>> I think I kinda view TripleO as a 'best practices' project. Using<br>
> >>> OpenStack is a confusing experience, with a million different options<br>
> >>> and choices to make. TripleO provides users with an excellent guide.<br>
> >>> But the problem is that best practices change, and I think that<br>
> >>> perceived instability is dangerous for adoption of TripleO.<br>
> >>><br>
> >>> So having a TripleO library and its associated API be a 'best<br>
> >>> practices'<br>
> >>> library makes sense to me. It gives consumers a stable platform upon<br>
> >>> which to use TripleO, while allowing us to be flexible behind the<br>
> >>> scenes.<br>
> >>> The 'best practice' for Heat capabilities right now is a workaround,<br>
> >>> because it hasn't been judged to be suitable to go into Heat itself.<br>
> >>> If that changes, we get to shift as well - and all of these changes<br>
> >>> are<br>
> >>> invisible to the API consumer.<br>
> >><br>
> >><br>
> >> I mentioned this in my "Driving workflows with Mistral" thread but with<br>
> >> regards to stability I view say Heat's v1 API or Mistral's v2 API as<br>
> >> both being way more stable that what we could ever achieve with TripleO<br>
> >> API. The real trick to API stability with something like Heat or<br>
> >> Mistral is how we manage the inputs and outputs to Stacks and Workflows<br>
> >> themselves. So long as we are mindful of this I can't image an end user<br>
> >> (say a GUI writer or whoever) would really care whether they POST to<br>
> >> Mistral or something we've created. The nice thing about using other<br>
> >> OpenStack projects like Heat or Mistral is that they very likely have<br>
> >> better community and documentation around these things as well that we<br>
> >> would ever have.<br>
> >><br>
> >> The more I look at using Mistral for some of the cases that have been<br>
> >> brought up the more it seems to make sense for a lot of the workflows<br>
> >> we need. I don't believe we can achieve better stability by creating<br>
> >> what sounds more and more like a shim/proxy API rather than using the<br>
> >> versioned API's that OpenStack already provides.<br>
> >><br>
> >> There may be some corner cases where a "GUI helper" API comes into play<br>
> >> for some sort of caching or something. I'm not blocking anyone from<br>
> >> creating these sorts of features if they need them. And again if it is<br>
> >> something that could be added to an upstream OpenStack project like<br>
> >> Heat or Mistral I would look there first. So perhaps Zaqar for<br>
> >> websockets instead of rolling our own, this sort of thing.<br>
> >><br>
> >> What does concern me is that we are overstating what TripleO API should<br>
> >> actually contain should we choose to pursue it. Initially it was<br>
> >> positioned as the "TripleO workflow API". I think we now agree that we<br>
> >> probably shouldn't put all of our workflows behind it. So if our stance<br>
> >> has changed would it make sense to compile a new list of what we<br>
> >> believe belongs behind our own TripleO API vs. what we consider<br>
> >> workflows.<br>
> >><br>
> ><br>
> ><br>
> > I wonder if it would be helpful to get operator feedback here - show them<br>
> > the advantages/disadvantages of both options and to get a sense of what<br>
> > might be useful/necessary for them to use TripleO effectively?<br>
><br>
> (I'm going off on a tangent a bit, but please bear with me, i'm using<br>
> all that to support the point in the end. The implications of building a<br>
> TripleO API touch on various topics.)<br>
><br>
> Yes i think we should gather operator feedback. We already got some, but<br>
> we should gather more whenever possible.<br>
><br>
> One kind of (negative) feedback i've heard is that overcloud management<br>
> is too much of a "blackbox" compared to what operators are used to. The<br>
> feedback i recall was that it's hard to tell what is going to happen<br>
> when running an overcloud stack update, and that we cannot re-execute<br>
> the software config management independently.<br>
><br>
> Building another umbrella API to rule the already largely umbrella-like<br>
> deployment process (think what all responsibilities lie within the<br>
> tripleo-heat-templates codebase, and within the single 'overcloud' Heat<br>
> stack) would probably make matters more blackboxy and go further in the<br>
> direction of "i feel like i don't know what's happening to my cloud when<br>
> i use the management tool".<br>
><br>
> What i think could improve the situation for operators is trying to<br>
> chunk up what we already have into smaller, more independently operable<br>
> parts. The split-stack approach already discussed on the TripleO meeting<br>
> and on #tripleo could help with this. Essentially separating our<br>
> hardware management from our software config management. Being able to<br>
> re-apply software configuration without being afraid of having nodes<br>
> accidentally re-provisioned from scratch.<br>
><br>
> In general i think TripleO could be a little more "UNIXy" - composed of<br>
> smaller parts that make sense on their own, transparent to the operator,<br>
> more modular and modifiable, and in effect more receptive of how varying<br>
> are the real world deployment environments (various Neutron and Cinder<br>
> plugins, Keystone backends, composable set of services, custom node<br>
> types etc.).<br>
><br>
> Workflow persisted in a data-like fashion is probably more modifiable by<br>
> the operator than Python code of a REST API. We've seen hard assumptions<br>
> cause problems in the past. (Think the unoverridable CLI parameters<br>
> issue we used to have, and how we had to move to a model of "CLI<br>
> provides its values, but you can always override them or provide<br>
> additional ones with an environment file if needed", which we now use<br>
> extensively). I'm a bit concerned that building a new REST API on top of<br>
> everything would impose new rigid assumptions that could cause more harm<br>
> than good in the end. I'm concerned that it would be usable only for<br>
> very basic deployments, while the world of real deployments has its own<br>
> pace and requirements not fitting the "best practices" as defined by the<br>
> API, having to bypass the API far too often and slowly pushing it into<br>
> abandonment over time.<br>
><br>
> My mind is probably biased towards the the operator feedback that<br>
> resonated with me the most, i've heard pro-blackbox opinions too (though<br>
> not from operators yet IIRC). So take what i wrote just as my 2 cents,<br>
> but i think it's necessary to consider the above issues when thinking<br>
> about the implications of building a TripleO API.<br>
><br>
<br>
</div></div>Those are completely valid points, thanks for bringing them up!<br>
<br>
I think I should step back a bit and express my views from a different<br>
perspective (which I probably should have done far earlier). I've been<br>
working with a GUI application that deploys OpenStack using TripleO. The<br>
deprecation of Tuskar was somewhat disruptive, but it was understood that<br>
there are workarounds while we work towards a more permanent solution.<br>
<br>
What this application wants from TripleO is a set of APIs that provides<br>
confidence that they can use TripleO without the risk of having to<br>
fundamentally change their codebase if TripleO changes. TripleO needs<br>
to guarantee support for its deployment practices and to have a formal<br>
deprecation process if it moves to a different architecture.<br>
<br>
The proposed TripleO API spec differs from Tuskar in that (in my view)<br>
it's far lower level. There are operations to get/set various types of<br>
deployment parameters; there's an operation to deploy the result. None<br>
of that precludes us from, say, eventually adding options to allow the<br>
API to distinguish between hardware management and software config, or<br>
to add an operation to apply the software config.<br>
<br>
Another reason this is important is it addresses your point below:<br>
<span><br>
><br>
> Regarding the non-workflow kind of features we need for empowering GUI,<br>
> wouldn't those be useful for normal (tenant) Heat stack deployments in<br>
> the overcloud too? It sounds to me that features like "driving a Heat<br>
> stack deployment with the same powers from CLI or GUI", "updating a<br>
> CLI-created stack from GUI and vice versa", "understanding/parsing what<br>
> are the configuration options of my Heat templates" are all features<br>
> that are not specific to TripleO, and could be useful for tenant Heat<br>
> stacks too. So perhaps these should be implemented in Heat? If that<br>
> can't happen fast enough, then we might need to put some workarounds in<br>
> place for now, but it might be better if we didn't advertise those as a<br>
> stable solution.<br>
><br>
<br>
</span>I think TripleO benefits from controlling the access to these operations,<br>
simply because it allows the underlying TripleO architecture change<br>
without forcing integrators to change all their API calls. For example,<br>
let's say we create a TripleO API that gets/sets parameters in the form<br>
of a Heat environment file, and then deploys through Heat. If we want<br>
to move to having the deployment driven through a Mistral workflow, we<br>
can change the underlying code - write the parameters into a Mistral<br>
environment file, drive the deployment through Mistral - without<br>
affecting the outward facing API.<br></blockquote><div><br></div></div></div><div>I think this is a great point, and I think it has a ton of value from the point of<br></div><div>view for an external consumer. For the TripleO CLI and TripleO API, Mistral<br></div><div>would likely be fine as CI etc. would make sure they don't break each other.<br></div><div>This guarantee wouldn't exist for external consumers, granted we would<br></div><div>have the same potential issue with an API (regressions happen). However, <br>I think trying to put an API infront of Mistral is an extra layer of abstraction <br>that may not be needed. <br><br></div><div>I would like to see us use Mistral directly and as those workflows mature,<br></div><div>if it proves to be a difficult entry point for users we can create an API that<br></div><div>creates a clearer and nicer interface to the world of TripleO. This might not<br></div><div>create the ideal initial situation but if feels like the right way to go about <br></div><div>this, incrementally adding an interface as needed rather adding an API<br></div><div>just in-case.<br><br></div><div>Let's get the Mistral interface correct and see where they leaves us.<br></div></div></div></div></blockquote><div><br></div><div>Gah, I git sent a bit early. I said almost everything I wanted to add, but I just<br></div><div>wanted to say that I believe we can offer a stable API via Mistral just in the <br></div><div>way we can with a custom API. We just need to clearly define and document<br></div><div>each of these points of contact. Then CI in TripleO hould help us avoid any<br></div><div>regressions or unplanned changes.<br></div><div><br></div>It could be argued that the Mistral interface would be more stable as it already<br>exists and has been proven. We would be using this standard interface.<br></div><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div></div><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<span><font color="#888888"><br>
<br>
Mainn<br>
</font></span><div><div><br>
<br>
><br>
> Jirka<br>
><br>
> ><br>
> > Mainn<br>
> ><br>
> ><br>
> >><br>
> >> Dan<br>
> >><br>
> >>><br>
> >>> Mainn<br>
> >>><br>
> >>><br>
> >>>><br>
> >>>>> I think the correct attitude is to simply look at the problem<br>
> >>>>> we're<br>
> >>>>> trying to solve and find the correct architecture. For these<br>
> >>>>> get/set<br>
> >>>>> methods that the API needs, it's pretty simple: storage -> some<br>
> >>>>> logic -><br>
> >>>>> a REST API. Adding a workflow engine on top of that is unneeded,<br>
> >>>>> and I<br>
> >>>>> believe that means it's an incorrect solution.<br>
> >>>><br>
> >>>> What may help is if we can work through the proposed API spec, and<br>
> >>>> identify which calls can reasonably be considered workflows vs<br>
> >>>> those where<br>
> >>>> it's really just proxying an API call with some logic?<br>
> >>>><br>
> >>>> When we have a defined list of "not workflow" API requirements,<br>
> >>>> it'll<br>
> >>>> probably be much easier to rationalize over the value of a bespoke<br>
> >>>> API vs<br>
> >>>> mistral?<br>
> >>>><br>
> >>>><br>
> >>>> Steve<br>
> >>>><br>
> >>>> ___________________________________________________________________<br>
> >>>> _______<br>
> >>>> OpenStack Development Mailing List (not for usage questions)<br>
> >>>> Unsubscribe: <a href="http://OpenStack-dev-request@lists.openstack.org?subject:unsu" rel="noreferrer" target="_blank">OpenStack-dev-request@lists.openstack.org?subject:unsu</a><br>
> >>>> bscribe<br>
> >>>> <a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" rel="noreferrer" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
> >>>><br>
> >>><br>
> >>> _____________________________________________________________________<br>
> >>> _____<br>
> >>> OpenStack Development Mailing List (not for usage questions)<br>
> >>> Unsubscribe: <a href="http://OpenStack-dev-request@lists.openstack.org?subject:unsubs" rel="noreferrer" target="_blank">OpenStack-dev-request@lists.openstack.org?subject:unsubs</a><br>
> >>> cribe<br>
> >>> <a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" rel="noreferrer" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
> >><br>
> >> __________________________________________________________________________<br>
> >> OpenStack Development Mailing List (not for usage questions)<br>
> >> Unsubscribe: <a href="http://OpenStack-dev-request@lists.openstack.org?subject:unsubscribe" rel="noreferrer" target="_blank">OpenStack-dev-request@lists.openstack.org?subject:unsubscribe</a><br>
> >> <a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" rel="noreferrer" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
> >><br>
> ><br>
> > __________________________________________________________________________<br>
> > OpenStack Development Mailing List (not for usage questions)<br>
> > Unsubscribe: <a href="http://OpenStack-dev-request@lists.openstack.org?subject:unsubscribe" rel="noreferrer" target="_blank">OpenStack-dev-request@lists.openstack.org?subject:unsubscribe</a><br>
> > <a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" rel="noreferrer" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
> ><br>
><br>
><br>
> __________________________________________________________________________<br>
> OpenStack Development Mailing List (not for usage questions)<br>
> Unsubscribe: <a href="http://OpenStack-dev-request@lists.openstack.org?subject:unsubscribe" rel="noreferrer" target="_blank">OpenStack-dev-request@lists.openstack.org?subject:unsubscribe</a><br>
> <a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" rel="noreferrer" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
><br>
<br>
__________________________________________________________________________<br>
OpenStack Development Mailing List (not for usage questions)<br>
Unsubscribe: <a href="http://OpenStack-dev-request@lists.openstack.org?subject:unsubscribe" rel="noreferrer" target="_blank">OpenStack-dev-request@lists.openstack.org?subject:unsubscribe</a><br>
<a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" rel="noreferrer" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
</div></div></blockquote></div></div></div><br></div></div>
</blockquote></div><br></div></div>