[openstack-dev] 答复: [quantum] [LBaaS] Health monitors REST resource
Leon Cui
lcui at vmware.com
Fri Nov 23 00:32:14 UTC 2012
Hi all,
If look at F5 approach on health monitor, user need to create a set of
health monitors first and then associate one or more health monitors to
the pool (or members). Internally, multiple health monitor instances are
created and associated with each member.
My take-aways are that:
1. Health monitor is a top resource to be managed;
2. Health monitor instances are not operated directly by user
(though user can still query them)
3. Query a pool will also get the health monitors associated.
I think our current API is aligned with this approach except that we don¡¯
t expose health monitor instance concept. I agree with Youcef that adding
more concepts to health monitor management will make it complicated. As
long as we can answer the two questions (mentioned in Youcel¡¯s mail),
current API should be in good shape.
For pool members, I agree with Salvatore that we should have a single way
of doing that, which is that approach 1 mentioned in Youcef¡¯s mail:
1. Create an empty pool, and then create members using the created
pool_id
Thanks
Leon
·¢¼þÈË: Salvatore Orlando [mailto:sorlando at nicira.com]
·¢ËÍʱ¼ä: 2012Äê11ÔÂ23ÈÕ 5:27
ÊÕ¼þÈË: OpenStack Development Mailing List
Ö÷Ìâ: Re: [openstack-dev] [quantum] [LBaaS] Health monitors REST resource
Hi again,
For health monitors, I think we are discussing two equally viable
approaches. Both have pro and cons. As Youcef said, introducing a
'template' for the health monitor adds a new resource, and an intermediate
step we probably don't want to expose to the user; I personally see the
fact that health monitors are usually mapped 1:1 on correspoinding
back-end API as somewhat less relevant, as I'd like to adopt a perspective
completely focused on the user. On the other hand, we have discussed the
cons of handling reference to health monitors as a collection attribute
within pools. I am taking for granted that you are discounting the idea of
having a 'list' attribute (as fixed_ips for the port resource), even if
that is not perfect as well it probably is the simplest from a user
perspective.
If we go the sub-resource-like route (current proposal), we'll need to do
some work on the Quantum API framework for supporting it. I will be more
than happy to this piece of work.
For pool members, I'd rather have a single way of doing thing rather than
two. I think it is more natural to specify the pool_id in the member
resource.
Thanks,
Salvatore
On 22 November 2012 20:37, Youcef Laribi <Youcef.Laribi at eu.citrix.com>
wrote:
Hi Oleg,
My intention was to keep the same APIs we have for
associating/dissociating a pool with a health_monitor. The new APIs will
be used for retrieving (GET).
Yes, I know it¡¯s not ideal because a health_monitor looks like a
sub-resource of pool in the associate/dissociate calls (doing it the other
way around is no better either), but I don¡¯t think it¡¯s a big deal from
a user perspective, and will keep the API simple instead of introducing a
new REST entity.
Thanks
Youcef
From: Oleg Bondarev [mailto:obondarev at mirantis.com]
Sent: Thursday, November 22, 2012 2:05 AM
To: 'OpenStack Development Mailing List'
Subject: Re: [openstack-dev] [quantum] [LBaaS] Health monitors REST
resource
Hi Youcef,
I have one question here: with what API calls do you suggest to
associate/disassociate health monitors with a pool?
Thanks,
Oleg
From: Youcef Laribi [mailto:Youcef.Laribi at eu.citrix.com]
Sent: Thursday, November 22, 2012 12:12 AM
To: OpenStack Development Mailing List
Subject: Re: [openstack-dev] [quantum] [LBaaS] Health monitors REST
resource
Hi Salvatore,
Thank you for your thorough analysis and helping the team reconcile a good
API design with an easy way to implement it.
I think we need to make a distinction between pool members and health
monitors.
Indeed the former exist only within a pool [1], whereas the latter can be
defined without any pool [2].
So for the pool members, I agree we probably don't want to specify them in
API calls for 'pool' resources.
In particular [3] seems strange in my opinion, as it is assuming the
members already exist. In another thread I think there was a suggestion to
make the member's pool_id attribute optional, but my opinion is that
probably we should remove the members attribute for the pool resource (at
least on create/update calls). It is fine IMHO to return a list of member
ids on GET operations for pools.
Yes today we have two ways of putting members into pools:
1. Create an empty pool, and then create members using the created
pool_id
2. Create members (with no pool_id) and then create a pool
containing those members
We can eliminate the second workflow to simplify as you suggested, so
there would be only one way of creating members in pools.
The question after this, is how do I get the members of a pool (a very
common operation). Here again, we have three possible ways:
1. Use filtering: GET /members?pool_id=1000
2. Have a dedicated REST API that reflects the fact the members
belong to a pool: GET /pools/1000/members
3. Return the list of members of a pool in the pool response payload
of: GET /pools/1000
I favor the second approach but I can settle for the 3rd one, even though
this requires more work from a user to find the ¡°members¡± attribute on
the response. What is your opinion on this?
Instead the health monitors are slightly different, since they are in a
n:m relationship with the pool resource. pool and pool members are instead
on a 1:n relationship.
The approach currently adopted in the API specification [4] makes sense
from a REST perspective. IMHO it makes more sense than having distinct
member action such as:
PUT /pools/<pool-id>/associate_health_monitor and PUT
/pools/<pool-id>/disassociate_health_monitor. As some contributors to this
thread have pointed out, this can generate confusion in final users, as
they might wonder whether an id or a full object definition is required.
In that case I would consider the following:
{POST/DELETE} /pools/<pool-id>/health_monitor_ids
Sub-resources map very well onto a ORM model.
Yes we are on the same page here, although I favor calling the
sub-resource simply ¡°health_monitors¡± instead of ¡°health_monitor_ids¡±
or ¡°health_monitor_references¡±, purely from an aesthetic perspective,
but I haven¡¯t got a strong opinion on this.
However, let's imagine you want to retrieve the list of pools which are
using a health_monitor. How would you do that? In theory you could add
that filter to the pools resource, so:
GET /pools?health_monitor_id=<your_health_monitor> would return you this
kind of list.
With this approach it is important to keep in mind is that a GET /pools is
supposed to look only into 'pool' resources. Adding this kind of
capability would require us to do joins according to the type of filter
specified (and we will also have to document it). No big deal, but still
something to keep in mind.
Yes this call doesn¡¯t make sense since there is currently no attribute
called ¡°health_monitor_id¡± in a pool resource you can filter on. User
can accomplish this themselves by retrieving all pool¡¯s health monitor
associations, and filtering the ones that contain the health_monitor of
interest
GET /pools/1000/health_monitors
GET /pools/2000/health_monitors
Etc.
After all, these kind of request ¡°which pools use monitor X¡± are not
very common or necessary for the workflow of the service. There would be a
lot many more questions like this that cannot be directly mapped to an API
call, and need the user to do some filtering and joining on their own.
An alternative is to regard the health_monitor as a 'template'. I am not
sure if this is valid within the LB world, but I have the impression it is
ok to assume that a health monitor does not actually exist until it is
associated with a pool.
In NetScaler, F5 and similar products, health monitors are created
beforehand just like in the API, and then they are ¡°bound¡± to pools (our
association API), so the mapping will be more natural.
In this case 'definitions' for health monitors could be managed in the
following way:
{ GET/POST/PUT/DELETE } /health-monitor-templates
And association/disassociation with pools can be managed in the following
way:
{GET/POST/DELETE} /health-monitors
The response here would look like the following:
{
"health_monitor_id": "uuid",
"health_monitor_template_id": "another-uuid",
"pool_id": "yet-another-uuid"
}
I think both approaches are equivalent. The first is represents a good
mapping on the ORM model, while the second a mapping on the ER model.
The first will need work to the Quantum's framework, whereas the latter
can be implemented using the framework as it is.
I have a slight preference for the second option, but no strong opinion,
as I believe the first approach makes sense too.
I think adding a concept of health_monitor templates just complicate
matters even more. The issue we have is not how to associate monitors and
pools, these are simple API calls, but answering the following questions
1. What are the health_monitors associated with a pool?
2. What are the pools associated with a health monitor?
I propose when retrieving a pool, we simply return the list of
health_monitors associated with it, and for a health_monitor the list of
pools associated with it. These are only returned for GET (they are
read-only attributes), they are not used for creation or update (we use
the associate/dissociate APIs already there), so this would translate in
answering the above questions to this:
1. Health monitors associated with a pool: GET /pools/{pool_id}
(response contains a ¡°health_monitors¡± (or health_monitor_ids J)
attribute)
2. Pools associated with a health_monitor: GET
/health_monitors/{health_monitor_id} (response contains a ¡°pools¡±
attribute)
This way we avoid the issue of sub-resource modeling, and keep the API
simple (at a cost of slightly more work for the API caller). What do you
think?
Youcef
On 20 November 2012 09:51, Oleg Bondarev <obondarev at mirantis.com> wrote:
Hi Youcef, team,
AFAIK python clients (quantum, nova, etc.) usually expose both CLI and
python API which I believe should be used in Horizon and other projects.
So I still think that python-quantumclient is the right place for adding
shortcuts.
A agree that improving api/v2 to support sub-resources is a good idea and
will be useful. I also agree that ¡°GET /v1.0/pools/{pool_id}/members¡±
looks natural but only in case when member is an actual sub-resource of a
pool. Resources and sub-resources in the Quantum extension framework are
distinctly separated. In our case members and health monitors are top
level resources ¨C so adding them also as sub-resources is kind of hack,
and may be misleading for those who reads the code ¨C all for the sake of
having shortcuts in REST.
>From my point of view it¡¯s clear enough from our REST API that members
belong to a pool since they have pool_id field and pool in its turn has
members field.
Hey we have a pretty long discussion here J, would be great to hear
anybody else from the team and make a final decision.
Salvatore, could you please share your thoughts?
Thanks,
Oleg
From: Youcef Laribi [mailto:Youcef.Laribi at eu.citrix.com]
Sent: Tuesday, November 20, 2012 1:01 AM
To: OpenStack Development Mailing List
Subject: Re: [openstack-dev] [quantum] [LBaaS] Health monitors REST
resource
Yes Oleg, some people will use the CLI to drive the LBaaS service, Horizon
portal will use the API, and other applications will use mainly the API.
Most people will understand the service by reading its APIs.
Yes, you can list the members of pool 1000 through query string filtering
by doing:
GET /v1.0/members?pool_id=1000
But as I said before, it¡¯s more natural to use the following to get the
pool¡¯s members:
GET /v1.0/pools/{pool_id}/members
Since members really belong to a pool. As you said, if we are improving
Quantum to support REST sub-resources then this is the preferred approach
I would advocate.
Youcef
From: Oleg Bondarev [mailto:obondarev at mirantis.com]
Sent: Monday, November 19, 2012 1:23 AM
To: 'OpenStack Development Mailing List'
Subject: Re: [openstack-dev] [quantum] [LBaaS] Health monitors REST
resource
I also surely agree that ¡°/pools/{pool_id}/health_monitor_references¡°
looks ugly and I don¡¯t want it to look like this.
My only concern is that treating health monitor references as a
sub-resource (and hence changes in api/v2) brings additional complexity to
the code when it can be done simpler: using filters for listing health
monitors of a pool and member actions for associate/disassociate (as in l3
extension). But probably it is ok given that handling sub-resources may be
useful in future anyway.
Another question I have is: where will these REST calls be used except
python-quantumclient? I thought that only client api matters for end
users. So the purpose of having kind of shortcuts for listing members and
health monitors of a pool in REST API (instead of using filters) is not
completely clear for me.
Thanks,
Oleg
From: Salvatore Orlando [mailto:sorlando at nicira.com]
Sent: Friday, November 16, 2012 9:32 PM
To: OpenStack Development Mailing List
Subject: Re: [openstack-dev] [quantum] [LBaaS] Health monitors REST
resource
Hi Youcef,
Thanks for the clarification. I was pretty sure this was well thought in
the API design, as I wrote in my previous post :)
The naming for the attribute on the pool which references health_monitors
is a discussion worth having. I have very little data points for
comparison with other parts of Quantum and Openstack APIs. The only
similar bit is probably the network-subnet relationship. In the response
for a GET /networks/<network-id> a list of subnet identifiers is returned.
The name for the list attribute is just 'subnets'. However, as this is a
read-only attribute there is no need for handling it as a sub-resource.
Response sample is available at [1]
Between handling the collection of health monitor references as a
sub-resource and having member actions for CRUD operations, I prefer the
first solution. I am happy to offer any kind of supports for the relevant
changes in the apiv2 modules. The other option is to regard
health_monitors as a 'list' attribute. Which means that a POST/PUT will
create/update the whole list. This is practical from server-side
perspective, but has also drawbacks. Indeed it adds burden to the client;
for instance, in order to add an element to the list you'll need a GET and
then a PUT; and it also causes confusion because of the fact that our PUT
actually implement patch semantics.
Salvatore
[1]
http://docs.openstack.org/api/openstack-network/2.0/content/List_Networks_
Detail.html#d6e858
On 16 November 2012 18:04, Youcef Laribi <Youcef.Laribi at eu.citrix.com>
wrote:
Changing the subject line¡
Health monitors ¡°/health_monitors/¡± are a top resource in the API and
are retrieved/added/removed/updated through their CRUD operations on this
top resource.
The subresource ¡°/pools/{pool_id}/health_monitors¡° is used for
associating already existing health monitors (created above) with an
existing pool, or for retrieving the health monitors associated with a
pool. It is a collection (list) that only contain IDs of health monitors
not the health monitors themselves. We can call this resource
¡°/pools/{pool_id}/health_monitor_references¡° or
¡°/pools/{pool_id}/pool_health_monitors¡± if we like, but I felt this was
ugly and I think there is no issue or ambiguity in the definition of API
itself as all operations are clearly described. But if you think changing
its name helps, I can do that J Would like to hear what others in the team
think.
Youcef
From: Oleg Bondarev [mailto:obondarev at mirantis.com]
Sent: Friday, November 16, 2012 1:12 AM
To: Youcef Laribi; 'OpenStack Development Mailing List'
Subject: RE: [openstack-dev] [quantum] Quantum extension framework issue
Hi guys,
I just want to clarify some things regarding health monitors in LBaaS API:
actually it is not completely a sub-resource of pool objects.
According to the API it is a separate resource which can be
added/showed/updated/deleted (with GET/POST.. ¡°/v1.0/health_monitors/..¡±
rest calls) in order to be reusable in different pools and probably
anywhere else as Sasha mentioned. Youcef please correct me if I am wrong
here.
Speaking about sub-resources I think following rest call:
POST /v1.0/pools/{pool_id}/health_monitors
is intended to create a sub-resource of health monitor for the pool and
not to add an existing health monitor to the pool.
Also I think having health monitors as a separate resource and as a
sub-resource of a pool at the same time is not correct.
So my vision is to leave health monitors as a separate resource and to use
member actions for the purpose of getting/associating/disassociating
health monitors with a pool:
Get health monitors of a pool:
GET /v1.0/pools/{pool_id}/get_health_monitors
Associate health monitors with a pool:
PUT /v1.0/pools/{pool_id}/add_health_monitors
{
"health_monitors" : [
"f3eeab00-8367-4524-b662-55e64d4cacb5"
]
}
Disassociate health monitors from a pool:
PUT /v1.0/pools/{pool_id}/delete_health_monitors
{
"health_monitors" : [
"f3eeab00-8367-4524-b662-55e64d4cacb5"
]
}
Please share your thoughts.
Thanks,
Oleg
From: Sasha Ratkovic [mailto:sasharatkovic at juniper.net]
Sent: Friday, November 16, 2012 3:38 AM
To: OpenStack Development Mailing List
Subject: Re: [openstack-dev] [quantum] Quantum extension framework issue
One comment: even though health_monitor is introduced as part of LB
effort, it has more general applicability. So having it under LB specific
resource may pose usability problems down the road when new services are
introduced, if health monitor is to be re-used for that purpose. One
solution is to make it "first class" citizen with relationship to "pool"
and/or make "pool" assume more abstract pooling semantics, reusable as
well across multiple services in the future. (yes, I am talking about
"groups" here :) ).
From: Salvatore Orlando <sorlando at nicira.com>
Reply-To: OpenStack Development Mailing List
<openstack-dev at lists.openstack.org>
Date: Thursday, November 15, 2012 7:40 AM
To: OpenStack Development Mailing List <openstack-dev at lists.openstack.org>
Subject: Re: [openstack-dev] [quantum] Quantum extension framework issue
Hi Oleg,
This is exactly what I was talking about.
One thing you might want to consider before choosing for one direction or
the other is that at the moment Quantum API does not use sub resources at
all.
There was a long discussion on this regard while designing the v2 API. The
gist of the discussion was that if a resource needed sub-resources then
there was a case for a sub-resource to become a 'first citizen' in the
API. I am pretty sure you already have mulled over whether health_monitors
should be a resource of their own, a sub resource of the pool, or a
multi-valued attribute of the pool, but I wanted to give you a heads-up
anyway.
On your technical questions I have some answers inline.
Salvatore
On 15 November 2012 15:40, Oleg Bondarev <obondarev at mirantis.com> wrote:
Hi folks,
As Salvatore said there is a way to specify parent for a resource (see
quantum.extensions.extensions.ResourceExtension) which allows route
mapping for rest calls like:
POST /v1.0/pools/{pool_id}/health_monitors
DELETE /v1.0/pools/{pool_id}/health_monitors/{id}
¡
In this case corresponding resource controller should be aware of resource
parent and be able to handle CRUD operations with an additional parent_id
parameter. Currently it doesn¡¯t. Actually I am speaking about
quantum.api.v2.base.Controller ¨C so, Salvatore, do you think it is the
right place to include sub-resource/parent handling?
Working on controllers in quantum.api.v2 is the best option in my opinion.
This however depends on how the route mapper associates controllers with
sub resources. Currently, the extension framework and the core API use two
distinct code paths: the former uses
quantum.extensions.extensions.ExtensionMiddleware whereas the latter uses
quantum.api.v2.router.APIRouter (this is for historical reasons only; as
far as I can recall, there's no technical reason for this). The Extension
Middleware has a mechanism for mapping associating parent resources to a
mapped resource, whereas the APIRouter does not have such mechanism.
As the controller does not care about how URI paths are mapped on its
methods, the only thing we probably need to worry about is how to make
sure that the parent resource id is passed to the controller for the
sub-resource. To this aim, I would probably define a new controller which
extends the base one rather than modifying quantum.api.v2.base.Controller.
Btw, there is of course the hackish way of skipping base.create_resource
and passing to ResourceExtension an object providing implementation for
the appropriate methods. I am totally sure you're aware of this option
too, but I would consider it only a last resort.
And also how do you guys think should this improvement be done as a
separate patch?
Separate patches in these cases are always preferred.
Thanks,
Oleg
From: Youcef Laribi [mailto:Youcef.Laribi at eu.citrix.com]
Sent: Wednesday, November 14, 2012 11:03 PM
To: OpenStack Development Mailing List
Subject: Re: [openstack-dev] [quantum] Quantum extension framework issue
Oleg,
The ¡°/pools/{pool_id}/health_monitors¡± REST resource is intended to be a
collection sub-resource of the ¡°/pools/{pool_id}¡± resource, so if the
Quantum WSGI framework can be improved to support REST sub-resources that
would be better and cleaner.
Youcef
From: Salvatore Orlando [mailto:sorlando at nicira.com]
Sent: Wednesday, November 14, 2012 10:00 AM
To: OpenStack Development Mailing List
Subject: Re: [openstack-dev] [quantum] Quantum extension framework issue
Hi Oleg,
When I read your first email, I had the same impression as Dan.
health_monitors look more like a subresource than an action.
The WSGI framework at the moment is not able to manage subresources; this
does not mean we cannot improve it though. Nevertheless, in this case the
route mapping is not performed by the API classes in quantum/api, but by
the extension manager. I think there should already be a way for
specifying parent resources with extensions, but that needs to be
explored.
It seems however that you are now trying to map operations on health
monitors using distinct member actions (add_health_monitor,
get_health_monitors). This is similar to what happens with the L3 API for
router interfaces.
However, it seems the original idea behind the API design was to treat
health_monitors as an explicit collection, which would also be probably a
more 'restful' way of doing it. I think ultimately the question should be
directed to Youcef and the team which contributed to the design of the
LBaaS API.
On 14 November 2012 17:18, Oleg Bondarev <obondarev at mirantis.com> wrote:
Hi Dan,
Thanks for your comment here.
Just wanted to correct a mistake in my first email: of course there can¡¯t
be a dict with duplicate keys. The idea was to use list of pairs, like:
member_actions = [{¡°health_monitors¡±: ¡°GET¡±},
{¡°health_monitors¡±: ¡°POST¡±}]
to have an ability of using same function name with different request
actions. Initially I thought that the framework provides such ability but
does not dispatch requests correctly. I was wrong.
Actually there is no issue with the framework as it assumes using unique
action names for different request methods.
I believe we should update LBaaS REST API doc and use
¡°get_health_monitors¡±, ¡°add_health_monitors¡±, etc. to fit in the
framework.
Thanks,
Oleg
From: Dan Wendlandt [mailto:dan at nicira.com]
Sent: Wednesday, November 14, 2012 7:27 PM
To: OpenStack Development Mailing List
Subject: Re: [openstack-dev] [quantum] Quantum extension framework issue
Hi Oleg,
Folks from the API-subteam can correct me, but I believe this use model is
outside of what the API framework was trying to enable with "actions".
The idea is that you use POST/DELETE to create an delete API "resources"
(which actually have UUIDs, for example, the "pool" in your example below)
and then do a PUT to an "action" to cause some kind of change that you can
affect on a resource (e.g., "add_health_monitor" or
"remove_health_monitor"). It sounds like what you are proposing is more
treating "health_monitors" almost as a "sub-resource", which is not really
what the "actions" stuff was designed for.
I haven't been deeply involved in the LBaaS api design discussion though,
so I'd also like to hear from Salvatore, et al. on the API sub-team.
Dan
On Wed, Nov 14, 2012 at 6:05 AM, Oleg Bondarev <obondarev at mirantis.com>
wrote:
Hi guys,
While working on the API extension for LBaaS I didn¡¯t find a way to use
custom member actions if they have the same name and differ only by
request method, for example
List all health monitors of a specific pool: GET
/pool/pool_id/health_monitors
Associate health monitors with a pool: POST /pool/pool_id/health_monitors
In quantum extension framework we pass ¡°health_monitors¡± as member
actions for a controller (quantum.api.v2.base.create_resource())
member_actions = {'health_monitors': 'GET',
'health_monitors': 'POST'}
controller = base.create_resource(collection_name,
resource_name,
plugin, params,
member_actions=member_actions)
According to the Controller implementation it dispatches all custom member
actions to its plugin attr:
def __getattr__(self, name):
if name in self._member_actions:
def _handle_action(request, id, body=None):
return getattr(self._plugin, name)(request.context, id,
body)
return _handle_action
else:
raise AttributeError
Where request.context is of type quantum.context.Context and does not
contain info about request method.
As a result there is no way to distinguish two custom actions in the
plugin.
Is it an issue in the framework?
Possible solution may be in concatenation of request method and action
name (¡°get_health_monitors¡±, ¡°post_health_monitors¡±) in a controller
before dispatching them to a plugin.
What do you think?
Thanks,
Oleg
_______________________________________________
OpenStack-dev mailing list
OpenStack-dev at lists.openstack.org
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
--
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Dan Wendlandt
Nicira, Inc: www.nicira.com
twitter: danwendlandt
~~~~~~~~~~~~~~~~~~~~~~~~~~~
_______________________________________________
OpenStack-dev mailing list
OpenStack-dev at lists.openstack.org
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
_______________________________________________
OpenStack-dev mailing list
OpenStack-dev at lists.openstack.org
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
_______________________________________________
OpenStack-dev mailing list
OpenStack-dev at lists.openstack.org
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
_______________________________________________
OpenStack-dev mailing list
OpenStack-dev at lists.openstack.org
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
_______________________________________________
OpenStack-dev mailing list
OpenStack-dev at lists.openstack.org
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openstack.org/pipermail/openstack-dev/attachments/20121122/96cbbf4e/attachment.html>
More information about the OpenStack-dev
mailing list