[openstack-dev] [quantum] [LBaaS] Health monitors REST resource

Oleg Bondarev obondarev at mirantis.com
Wed Nov 21 15:29:04 UTC 2012


Hi Salvatore,

 

Thank you very much for such a deep research on this! 

The second approach seems more preferable for me too and I vote for it J
Although the first one maps good on the ORM model IMHO health_monitor_id as
a sub-resource doesn't look nice.

 

Thanks,

Oleg

 

From: Salvatore Orlando [mailto:sorlando at nicira.com] 
Sent: Wednesday, November 21, 2012 6:23 PM
To: OpenStack Development Mailing List
Subject: Re: [openstack-dev] [quantum] [LBaaS] Health monitors REST resource

 

Hi Folks,

 

my apologies for the delay. Unfortunately I missed the last message on this
thread. I'm a naughty boy :)

Many thanks to Oleg for sending me a reminder.

 

I've looked back at the discussion on this thread and at the API
specification.

 

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.

 

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. 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.

 

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 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.

 

Salvatore

 

[1] http://wiki.openstack.org/Quantum/LBaaS/API_1.0#Create_Pool_Members

[2] http://wiki.openstack.org/Quantum/LBaaS/API_1.0#Create_a_Health_Monitor

[3] http://wiki.openstack.org/Quantum/LBaaS/API_1.0#Create_a_Pool

[4]
http://wiki.openstack.org/Quantum/LBaaS/API_1.0#Associate_Health_Monitors_wi
th_a_Pool

 

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 - so adding them also as sub-resources is kind of hack, and may be
misleading for those who reads the code - 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_De
tail.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 - 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

 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openstack.org/pipermail/openstack-dev/attachments/20121121/792ef121/attachment.html>


More information about the OpenStack-dev mailing list