Re: [openstack-dev] [neutron][ml2] Port binding information, transactions, and concurrency

2014-02-19 Thread Robert Kukura
On 02/10/2014 05:46 AM, Mathieu Rohon wrote:
 Hi,
 
 one other comment inline :

Hi Mathieu, see below:

 
 On Wed, Feb 5, 2014 at 5:01 PM, Robert Kukura rkuk...@redhat.com wrote:
 On 02/05/2014 09:10 AM, Henry Gessau wrote:
 Bob, this is fantastic, I really appreciate all the detail. A couple of
 questions ...

 On Wed, Feb 05, at 2:16 am, Robert Kukura rkuk...@redhat.com wrote:

 A couple of interrelated issues with the ML2 plugin's port binding have
 been discussed over the past several months in the weekly ML2 meetings.
 These effect drivers being implemented for icehouse, and therefore need
 to be addressed in icehouse:

 * MechanismDrivers need detailed information about all binding changes,
 including unbinding on port deletion
 (https://bugs.launchpad.net/neutron/+bug/1276395)
 * MechanismDrivers' bind_port() methods are currently called inside
 transactions, but in some cases need to make remote calls to controllers
 or devices (https://bugs.launchpad.net/neutron/+bug/1276391)
 * Semantics of concurrent port binding need to be defined if binding is
 moved outside the triggering transaction.

 I've taken the action of writing up a unified proposal for resolving
 these issues, which follows...

 1) An original_bound_segment property will be added to PortContext. When
 the MechanismDriver update_port_precommit() and update_port_postcommit()
 methods are called and a binding previously existed (whether its being
 torn down or not), this property will provide access to the network
 segment used by the old binding. In these same cases, the portbinding
 extension attributes (such as binding:vif_type) for the old binding will
 be available via the PortContext.original property. It may be helpful to
 also add bound_driver and original_bound_driver properties to
 PortContext that behave similarly to bound_segment and
 original_bound_segment.

 2) The MechanismDriver.bind_port() method will no longer be called from
 within a transaction. This will allow drivers to make remote calls on
 controllers or devices from within this method without holding a DB
 transaction open during those calls. Drivers can manage their own
 transactions within bind_port() if needed, but need to be aware that
 these are independent from the transaction that triggered binding, and
 concurrent changes to the port could be occurring.

 3) Binding will only occur after the transaction that triggers it has
 been completely processed and committed. That initial transaction will
 unbind the port if necessary. Four cases for the initial transaction are
 possible:

 3a) In a port create operation, whether the binding:host_id is supplied
 or not, all drivers' port_create_precommit() methods will be called, the
 initial transaction will be committed, and all drivers'
 port_create_postcommit() methods will be called. The drivers will see
 this as creation of a new unbound port, with PortContext properties as
 shown. If a value for binding:host_id was supplied, binding will occur
 afterwards as described in 4 below.

 PortContext.original: None
 PortContext.original_bound_segment: None
 PortContext.original_bound_driver: None
 PortContext.current['binding:host_id']: supplied value or None
 PortContext.current['binding:vif_type']: 'unbound'
 PortContext.bound_segment: None
 PortContext.bound_driver: None

 3b) Similarly, in a port update operation on a previously unbound port,
 all drivers' port_update_precommit() and port_update_postcommit()
 methods will be called, with PortContext properies as shown. If a value
 for binding:host_id was supplied, binding will occur afterwards as
 described in 4 below.

 PortContext.original['binding:host_id']: previous value or None
 PortContext.original['binding:vif_type']: 'unbound' or 'binding_failed'
 PortContext.original_bound_segment: None
 PortContext.original_bound_driver: None
 PortContext.current['binding:host_id']: current value or None
 PortContext.current['binding:vif_type']: 'unbound'
 PortContext.bound_segment: None
 PortContext.bound_driver: None

 3c) In a port update operation on a previously bound port that does not
 trigger unbinding or rebinding, all drivers' update_port_precommit() and
 update_port_postcommit() methods will be called with PortContext
 properties reflecting unchanged binding states as shown.

 PortContext.original['binding:host_id']: previous value
 PortContext.original['binding:vif_type']: previous value
 PortContext.original_bound_segment: previous value
 PortContext.original_bound_driver: previous value
 PortContext.current['binding:host_id']: previous value
 PortContext.current['binding:vif_type']: previous value
 PortContext.bound_segment: previous value
 PortContext.bound_driver: previous value

 3d) In a the port update operation on a previously bound port that does
 trigger unbinding or rebinding, all drivers' update_port_precommit() and
 update_port_postcommit() methods will be called with PortContext
 properties reflecting the previously bound and currently 

Re: [openstack-dev] [neutron][ml2] Port binding information, transactions, and concurrency

2014-02-19 Thread Robert Kukura
On 02/05/2014 10:47 AM, Mathieu Rohon wrote:
 Hi,
 
 thanks for this great proposal

Just following up on the one comment below:

 
 
 On Wed, Feb 5, 2014 at 3:10 PM, Henry Gessau ges...@cisco.com wrote:
 Bob, this is fantastic, I really appreciate all the detail. A couple of
 questions ...

 On Wed, Feb 05, at 2:16 am, Robert Kukura rkuk...@redhat.com wrote:

 A couple of interrelated issues with the ML2 plugin's port binding have
 been discussed over the past several months in the weekly ML2 meetings.
 These effect drivers being implemented for icehouse, and therefore need
 to be addressed in icehouse:

 * MechanismDrivers need detailed information about all binding changes,
 including unbinding on port deletion
 (https://bugs.launchpad.net/neutron/+bug/1276395)
 * MechanismDrivers' bind_port() methods are currently called inside
 transactions, but in some cases need to make remote calls to controllers
 or devices (https://bugs.launchpad.net/neutron/+bug/1276391)
 * Semantics of concurrent port binding need to be defined if binding is
 moved outside the triggering transaction.

 I've taken the action of writing up a unified proposal for resolving
 these issues, which follows...

 1) An original_bound_segment property will be added to PortContext. When
 the MechanismDriver update_port_precommit() and update_port_postcommit()
 methods are called and a binding previously existed (whether its being
 torn down or not), this property will provide access to the network
 segment used by the old binding. In these same cases, the portbinding
 extension attributes (such as binding:vif_type) for the old binding will
 be available via the PortContext.original property. It may be helpful to
 also add bound_driver and original_bound_driver properties to
 PortContext that behave similarly to bound_segment and
 original_bound_segment.

 2) The MechanismDriver.bind_port() method will no longer be called from
 within a transaction. This will allow drivers to make remote calls on
 controllers or devices from within this method without holding a DB
 transaction open during those calls. Drivers can manage their own
 transactions within bind_port() if needed, but need to be aware that
 these are independent from the transaction that triggered binding, and
 concurrent changes to the port could be occurring.

 3) Binding will only occur after the transaction that triggers it has
 been completely processed and committed. That initial transaction will
 unbind the port if necessary. Four cases for the initial transaction are
 possible:

 3a) In a port create operation, whether the binding:host_id is supplied
 or not, all drivers' port_create_precommit() methods will be called, the
 initial transaction will be committed, and all drivers'
 port_create_postcommit() methods will be called. The drivers will see
 this as creation of a new unbound port, with PortContext properties as
 shown. If a value for binding:host_id was supplied, binding will occur
 afterwards as described in 4 below.

 PortContext.original: None
 PortContext.original_bound_segment: None
 PortContext.original_bound_driver: None
 PortContext.current['binding:host_id']: supplied value or None
 PortContext.current['binding:vif_type']: 'unbound'
 PortContext.bound_segment: None
 PortContext.bound_driver: None

 3b) Similarly, in a port update operation on a previously unbound port,
 all drivers' port_update_precommit() and port_update_postcommit()
 methods will be called, with PortContext properies as shown. If a value
 for binding:host_id was supplied, binding will occur afterwards as
 described in 4 below.

 PortContext.original['binding:host_id']: previous value or None
 PortContext.original['binding:vif_type']: 'unbound' or 'binding_failed'
 PortContext.original_bound_segment: None
 PortContext.original_bound_driver: None
 PortContext.current['binding:host_id']: current value or None
 PortContext.current['binding:vif_type']: 'unbound'
 PortContext.bound_segment: None
 PortContext.bound_driver: None

 3c) In a port update operation on a previously bound port that does not
 trigger unbinding or rebinding, all drivers' update_port_precommit() and
 update_port_postcommit() methods will be called with PortContext
 properties reflecting unchanged binding states as shown.

 PortContext.original['binding:host_id']: previous value
 PortContext.original['binding:vif_type']: previous value
 PortContext.original_bound_segment: previous value
 PortContext.original_bound_driver: previous value
 PortContext.current['binding:host_id']: previous value
 PortContext.current['binding:vif_type']: previous value
 PortContext.bound_segment: previous value
 PortContext.bound_driver: previous value

 3d) In a the port update operation on a previously bound port that does
 trigger unbinding or rebinding, all drivers' update_port_precommit() and
 update_port_postcommit() methods will be called with PortContext
 properties reflecting the previously bound and currently unbound binding
 states 

Re: [openstack-dev] [neutron][ml2] Port binding information, transactions, and concurrency

2014-02-10 Thread Mathieu Rohon
Hi,

one other comment inline :

On Wed, Feb 5, 2014 at 5:01 PM, Robert Kukura rkuk...@redhat.com wrote:
 On 02/05/2014 09:10 AM, Henry Gessau wrote:
 Bob, this is fantastic, I really appreciate all the detail. A couple of
 questions ...

 On Wed, Feb 05, at 2:16 am, Robert Kukura rkuk...@redhat.com wrote:

 A couple of interrelated issues with the ML2 plugin's port binding have
 been discussed over the past several months in the weekly ML2 meetings.
 These effect drivers being implemented for icehouse, and therefore need
 to be addressed in icehouse:

 * MechanismDrivers need detailed information about all binding changes,
 including unbinding on port deletion
 (https://bugs.launchpad.net/neutron/+bug/1276395)
 * MechanismDrivers' bind_port() methods are currently called inside
 transactions, but in some cases need to make remote calls to controllers
 or devices (https://bugs.launchpad.net/neutron/+bug/1276391)
 * Semantics of concurrent port binding need to be defined if binding is
 moved outside the triggering transaction.

 I've taken the action of writing up a unified proposal for resolving
 these issues, which follows...

 1) An original_bound_segment property will be added to PortContext. When
 the MechanismDriver update_port_precommit() and update_port_postcommit()
 methods are called and a binding previously existed (whether its being
 torn down or not), this property will provide access to the network
 segment used by the old binding. In these same cases, the portbinding
 extension attributes (such as binding:vif_type) for the old binding will
 be available via the PortContext.original property. It may be helpful to
 also add bound_driver and original_bound_driver properties to
 PortContext that behave similarly to bound_segment and
 original_bound_segment.

 2) The MechanismDriver.bind_port() method will no longer be called from
 within a transaction. This will allow drivers to make remote calls on
 controllers or devices from within this method without holding a DB
 transaction open during those calls. Drivers can manage their own
 transactions within bind_port() if needed, but need to be aware that
 these are independent from the transaction that triggered binding, and
 concurrent changes to the port could be occurring.

 3) Binding will only occur after the transaction that triggers it has
 been completely processed and committed. That initial transaction will
 unbind the port if necessary. Four cases for the initial transaction are
 possible:

 3a) In a port create operation, whether the binding:host_id is supplied
 or not, all drivers' port_create_precommit() methods will be called, the
 initial transaction will be committed, and all drivers'
 port_create_postcommit() methods will be called. The drivers will see
 this as creation of a new unbound port, with PortContext properties as
 shown. If a value for binding:host_id was supplied, binding will occur
 afterwards as described in 4 below.

 PortContext.original: None
 PortContext.original_bound_segment: None
 PortContext.original_bound_driver: None
 PortContext.current['binding:host_id']: supplied value or None
 PortContext.current['binding:vif_type']: 'unbound'
 PortContext.bound_segment: None
 PortContext.bound_driver: None

 3b) Similarly, in a port update operation on a previously unbound port,
 all drivers' port_update_precommit() and port_update_postcommit()
 methods will be called, with PortContext properies as shown. If a value
 for binding:host_id was supplied, binding will occur afterwards as
 described in 4 below.

 PortContext.original['binding:host_id']: previous value or None
 PortContext.original['binding:vif_type']: 'unbound' or 'binding_failed'
 PortContext.original_bound_segment: None
 PortContext.original_bound_driver: None
 PortContext.current['binding:host_id']: current value or None
 PortContext.current['binding:vif_type']: 'unbound'
 PortContext.bound_segment: None
 PortContext.bound_driver: None

 3c) In a port update operation on a previously bound port that does not
 trigger unbinding or rebinding, all drivers' update_port_precommit() and
 update_port_postcommit() methods will be called with PortContext
 properties reflecting unchanged binding states as shown.

 PortContext.original['binding:host_id']: previous value
 PortContext.original['binding:vif_type']: previous value
 PortContext.original_bound_segment: previous value
 PortContext.original_bound_driver: previous value
 PortContext.current['binding:host_id']: previous value
 PortContext.current['binding:vif_type']: previous value
 PortContext.bound_segment: previous value
 PortContext.bound_driver: previous value

 3d) In a the port update operation on a previously bound port that does
 trigger unbinding or rebinding, all drivers' update_port_precommit() and
 update_port_postcommit() methods will be called with PortContext
 properties reflecting the previously bound and currently unbound binding
 states as shown. If a value for binding:host_id was supplied, 

Re: [openstack-dev] [neutron][ml2] Port binding information, transactions, and concurrency

2014-02-05 Thread Henry Gessau
Bob, this is fantastic, I really appreciate all the detail. A couple of
questions ...

On Wed, Feb 05, at 2:16 am, Robert Kukura rkuk...@redhat.com wrote:

 A couple of interrelated issues with the ML2 plugin's port binding have
 been discussed over the past several months in the weekly ML2 meetings.
 These effect drivers being implemented for icehouse, and therefore need
 to be addressed in icehouse:
 
 * MechanismDrivers need detailed information about all binding changes,
 including unbinding on port deletion
 (https://bugs.launchpad.net/neutron/+bug/1276395)
 * MechanismDrivers' bind_port() methods are currently called inside
 transactions, but in some cases need to make remote calls to controllers
 or devices (https://bugs.launchpad.net/neutron/+bug/1276391)
 * Semantics of concurrent port binding need to be defined if binding is
 moved outside the triggering transaction.
 
 I've taken the action of writing up a unified proposal for resolving
 these issues, which follows...
 
 1) An original_bound_segment property will be added to PortContext. When
 the MechanismDriver update_port_precommit() and update_port_postcommit()
 methods are called and a binding previously existed (whether its being
 torn down or not), this property will provide access to the network
 segment used by the old binding. In these same cases, the portbinding
 extension attributes (such as binding:vif_type) for the old binding will
 be available via the PortContext.original property. It may be helpful to
 also add bound_driver and original_bound_driver properties to
 PortContext that behave similarly to bound_segment and
 original_bound_segment.
 
 2) The MechanismDriver.bind_port() method will no longer be called from
 within a transaction. This will allow drivers to make remote calls on
 controllers or devices from within this method without holding a DB
 transaction open during those calls. Drivers can manage their own
 transactions within bind_port() if needed, but need to be aware that
 these are independent from the transaction that triggered binding, and
 concurrent changes to the port could be occurring.
 
 3) Binding will only occur after the transaction that triggers it has
 been completely processed and committed. That initial transaction will
 unbind the port if necessary. Four cases for the initial transaction are
 possible:
 
 3a) In a port create operation, whether the binding:host_id is supplied
 or not, all drivers' port_create_precommit() methods will be called, the
 initial transaction will be committed, and all drivers'
 port_create_postcommit() methods will be called. The drivers will see
 this as creation of a new unbound port, with PortContext properties as
 shown. If a value for binding:host_id was supplied, binding will occur
 afterwards as described in 4 below.
 
 PortContext.original: None
 PortContext.original_bound_segment: None
 PortContext.original_bound_driver: None
 PortContext.current['binding:host_id']: supplied value or None
 PortContext.current['binding:vif_type']: 'unbound'
 PortContext.bound_segment: None
 PortContext.bound_driver: None
 
 3b) Similarly, in a port update operation on a previously unbound port,
 all drivers' port_update_precommit() and port_update_postcommit()
 methods will be called, with PortContext properies as shown. If a value
 for binding:host_id was supplied, binding will occur afterwards as
 described in 4 below.
 
 PortContext.original['binding:host_id']: previous value or None
 PortContext.original['binding:vif_type']: 'unbound' or 'binding_failed'
 PortContext.original_bound_segment: None
 PortContext.original_bound_driver: None
 PortContext.current['binding:host_id']: current value or None
 PortContext.current['binding:vif_type']: 'unbound'
 PortContext.bound_segment: None
 PortContext.bound_driver: None
 
 3c) In a port update operation on a previously bound port that does not
 trigger unbinding or rebinding, all drivers' update_port_precommit() and
 update_port_postcommit() methods will be called with PortContext
 properties reflecting unchanged binding states as shown.
 
 PortContext.original['binding:host_id']: previous value
 PortContext.original['binding:vif_type']: previous value
 PortContext.original_bound_segment: previous value
 PortContext.original_bound_driver: previous value
 PortContext.current['binding:host_id']: previous value
 PortContext.current['binding:vif_type']: previous value
 PortContext.bound_segment: previous value
 PortContext.bound_driver: previous value
 
 3d) In a the port update operation on a previously bound port that does
 trigger unbinding or rebinding, all drivers' update_port_precommit() and
 update_port_postcommit() methods will be called with PortContext
 properties reflecting the previously bound and currently unbound binding
 states as shown. If a value for binding:host_id was supplied, binding
 will occur afterwards as described in 4 below.
 
 PortContext.original['binding:host_id']: previous value
 

Re: [openstack-dev] [neutron][ml2] Port binding information, transactions, and concurrency

2014-02-05 Thread Mathieu Rohon
Hi,

thanks for this great proposal


On Wed, Feb 5, 2014 at 3:10 PM, Henry Gessau ges...@cisco.com wrote:
 Bob, this is fantastic, I really appreciate all the detail. A couple of
 questions ...

 On Wed, Feb 05, at 2:16 am, Robert Kukura rkuk...@redhat.com wrote:

 A couple of interrelated issues with the ML2 plugin's port binding have
 been discussed over the past several months in the weekly ML2 meetings.
 These effect drivers being implemented for icehouse, and therefore need
 to be addressed in icehouse:

 * MechanismDrivers need detailed information about all binding changes,
 including unbinding on port deletion
 (https://bugs.launchpad.net/neutron/+bug/1276395)
 * MechanismDrivers' bind_port() methods are currently called inside
 transactions, but in some cases need to make remote calls to controllers
 or devices (https://bugs.launchpad.net/neutron/+bug/1276391)
 * Semantics of concurrent port binding need to be defined if binding is
 moved outside the triggering transaction.

 I've taken the action of writing up a unified proposal for resolving
 these issues, which follows...

 1) An original_bound_segment property will be added to PortContext. When
 the MechanismDriver update_port_precommit() and update_port_postcommit()
 methods are called and a binding previously existed (whether its being
 torn down or not), this property will provide access to the network
 segment used by the old binding. In these same cases, the portbinding
 extension attributes (such as binding:vif_type) for the old binding will
 be available via the PortContext.original property. It may be helpful to
 also add bound_driver and original_bound_driver properties to
 PortContext that behave similarly to bound_segment and
 original_bound_segment.

 2) The MechanismDriver.bind_port() method will no longer be called from
 within a transaction. This will allow drivers to make remote calls on
 controllers or devices from within this method without holding a DB
 transaction open during those calls. Drivers can manage their own
 transactions within bind_port() if needed, but need to be aware that
 these are independent from the transaction that triggered binding, and
 concurrent changes to the port could be occurring.

 3) Binding will only occur after the transaction that triggers it has
 been completely processed and committed. That initial transaction will
 unbind the port if necessary. Four cases for the initial transaction are
 possible:

 3a) In a port create operation, whether the binding:host_id is supplied
 or not, all drivers' port_create_precommit() methods will be called, the
 initial transaction will be committed, and all drivers'
 port_create_postcommit() methods will be called. The drivers will see
 this as creation of a new unbound port, with PortContext properties as
 shown. If a value for binding:host_id was supplied, binding will occur
 afterwards as described in 4 below.

 PortContext.original: None
 PortContext.original_bound_segment: None
 PortContext.original_bound_driver: None
 PortContext.current['binding:host_id']: supplied value or None
 PortContext.current['binding:vif_type']: 'unbound'
 PortContext.bound_segment: None
 PortContext.bound_driver: None

 3b) Similarly, in a port update operation on a previously unbound port,
 all drivers' port_update_precommit() and port_update_postcommit()
 methods will be called, with PortContext properies as shown. If a value
 for binding:host_id was supplied, binding will occur afterwards as
 described in 4 below.

 PortContext.original['binding:host_id']: previous value or None
 PortContext.original['binding:vif_type']: 'unbound' or 'binding_failed'
 PortContext.original_bound_segment: None
 PortContext.original_bound_driver: None
 PortContext.current['binding:host_id']: current value or None
 PortContext.current['binding:vif_type']: 'unbound'
 PortContext.bound_segment: None
 PortContext.bound_driver: None

 3c) In a port update operation on a previously bound port that does not
 trigger unbinding or rebinding, all drivers' update_port_precommit() and
 update_port_postcommit() methods will be called with PortContext
 properties reflecting unchanged binding states as shown.

 PortContext.original['binding:host_id']: previous value
 PortContext.original['binding:vif_type']: previous value
 PortContext.original_bound_segment: previous value
 PortContext.original_bound_driver: previous value
 PortContext.current['binding:host_id']: previous value
 PortContext.current['binding:vif_type']: previous value
 PortContext.bound_segment: previous value
 PortContext.bound_driver: previous value

 3d) In a the port update operation on a previously bound port that does
 trigger unbinding or rebinding, all drivers' update_port_precommit() and
 update_port_postcommit() methods will be called with PortContext
 properties reflecting the previously bound and currently unbound binding
 states as shown. If a value for binding:host_id was supplied, binding
 will occur afterwards as 

Re: [openstack-dev] [neutron][ml2] Port binding information, transactions, and concurrency

2014-02-05 Thread Robert Kukura
On 02/05/2014 09:10 AM, Henry Gessau wrote:
 Bob, this is fantastic, I really appreciate all the detail. A couple of
 questions ...
 
 On Wed, Feb 05, at 2:16 am, Robert Kukura rkuk...@redhat.com wrote:
 
 A couple of interrelated issues with the ML2 plugin's port binding have
 been discussed over the past several months in the weekly ML2 meetings.
 These effect drivers being implemented for icehouse, and therefore need
 to be addressed in icehouse:

 * MechanismDrivers need detailed information about all binding changes,
 including unbinding on port deletion
 (https://bugs.launchpad.net/neutron/+bug/1276395)
 * MechanismDrivers' bind_port() methods are currently called inside
 transactions, but in some cases need to make remote calls to controllers
 or devices (https://bugs.launchpad.net/neutron/+bug/1276391)
 * Semantics of concurrent port binding need to be defined if binding is
 moved outside the triggering transaction.

 I've taken the action of writing up a unified proposal for resolving
 these issues, which follows...

 1) An original_bound_segment property will be added to PortContext. When
 the MechanismDriver update_port_precommit() and update_port_postcommit()
 methods are called and a binding previously existed (whether its being
 torn down or not), this property will provide access to the network
 segment used by the old binding. In these same cases, the portbinding
 extension attributes (such as binding:vif_type) for the old binding will
 be available via the PortContext.original property. It may be helpful to
 also add bound_driver and original_bound_driver properties to
 PortContext that behave similarly to bound_segment and
 original_bound_segment.

 2) The MechanismDriver.bind_port() method will no longer be called from
 within a transaction. This will allow drivers to make remote calls on
 controllers or devices from within this method without holding a DB
 transaction open during those calls. Drivers can manage their own
 transactions within bind_port() if needed, but need to be aware that
 these are independent from the transaction that triggered binding, and
 concurrent changes to the port could be occurring.

 3) Binding will only occur after the transaction that triggers it has
 been completely processed and committed. That initial transaction will
 unbind the port if necessary. Four cases for the initial transaction are
 possible:

 3a) In a port create operation, whether the binding:host_id is supplied
 or not, all drivers' port_create_precommit() methods will be called, the
 initial transaction will be committed, and all drivers'
 port_create_postcommit() methods will be called. The drivers will see
 this as creation of a new unbound port, with PortContext properties as
 shown. If a value for binding:host_id was supplied, binding will occur
 afterwards as described in 4 below.

 PortContext.original: None
 PortContext.original_bound_segment: None
 PortContext.original_bound_driver: None
 PortContext.current['binding:host_id']: supplied value or None
 PortContext.current['binding:vif_type']: 'unbound'
 PortContext.bound_segment: None
 PortContext.bound_driver: None

 3b) Similarly, in a port update operation on a previously unbound port,
 all drivers' port_update_precommit() and port_update_postcommit()
 methods will be called, with PortContext properies as shown. If a value
 for binding:host_id was supplied, binding will occur afterwards as
 described in 4 below.

 PortContext.original['binding:host_id']: previous value or None
 PortContext.original['binding:vif_type']: 'unbound' or 'binding_failed'
 PortContext.original_bound_segment: None
 PortContext.original_bound_driver: None
 PortContext.current['binding:host_id']: current value or None
 PortContext.current['binding:vif_type']: 'unbound'
 PortContext.bound_segment: None
 PortContext.bound_driver: None

 3c) In a port update operation on a previously bound port that does not
 trigger unbinding or rebinding, all drivers' update_port_precommit() and
 update_port_postcommit() methods will be called with PortContext
 properties reflecting unchanged binding states as shown.

 PortContext.original['binding:host_id']: previous value
 PortContext.original['binding:vif_type']: previous value
 PortContext.original_bound_segment: previous value
 PortContext.original_bound_driver: previous value
 PortContext.current['binding:host_id']: previous value
 PortContext.current['binding:vif_type']: previous value
 PortContext.bound_segment: previous value
 PortContext.bound_driver: previous value

 3d) In a the port update operation on a previously bound port that does
 trigger unbinding or rebinding, all drivers' update_port_precommit() and
 update_port_postcommit() methods will be called with PortContext
 properties reflecting the previously bound and currently unbound binding
 states as shown. If a value for binding:host_id was supplied, binding
 will occur afterwards as described in 4 below.

 PortContext.original['binding:host_id']: 

[openstack-dev] [neutron][ml2] Port binding information, transactions, and concurrency

2014-02-04 Thread Robert Kukura
A couple of interrelated issues with the ML2 plugin's port binding have
been discussed over the past several months in the weekly ML2 meetings.
These effect drivers being implemented for icehouse, and therefore need
to be addressed in icehouse:

* MechanismDrivers need detailed information about all binding changes,
including unbinding on port deletion
(https://bugs.launchpad.net/neutron/+bug/1276395)
* MechanismDrivers' bind_port() methods are currently called inside
transactions, but in some cases need to make remote calls to controllers
or devices (https://bugs.launchpad.net/neutron/+bug/1276391)
* Semantics of concurrent port binding need to be defined if binding is
moved outside the triggering transaction.

I've taken the action of writing up a unified proposal for resolving
these issues, which follows...

1) An original_bound_segment property will be added to PortContext. When
the MechanismDriver update_port_precommit() and update_port_postcommit()
methods are called and a binding previously existed (whether its being
torn down or not), this property will provide access to the network
segment used by the old binding. In these same cases, the portbinding
extension attributes (such as binding:vif_type) for the old binding will
be available via the PortContext.original property. It may be helpful to
also add bound_driver and original_bound_driver properties to
PortContext that behave similarly to bound_segment and
original_bound_segment.

2) The MechanismDriver.bind_port() method will no longer be called from
within a transaction. This will allow drivers to make remote calls on
controllers or devices from within this method without holding a DB
transaction open during those calls. Drivers can manage their own
transactions within bind_port() if needed, but need to be aware that
these are independent from the transaction that triggered binding, and
concurrent changes to the port could be occurring.

3) Binding will only occur after the transaction that triggers it has
been completely processed and committed. That initial transaction will
unbind the port if necessary. Four cases for the initial transaction are
possible:

3a) In a port create operation, whether the binding:host_id is supplied
or not, all drivers' port_create_precommit() methods will be called, the
initial transaction will be committed, and all drivers'
port_create_postcommit() methods will be called. The drivers will see
this as creation of a new unbound port, with PortContext properties as
shown. If a value for binding:host_id was supplied, binding will occur
afterwards as described in 4 below.

PortContext.original: None
PortContext.original_bound_segment: None
PortContext.original_bound_driver: None
PortContext.current['binding:host_id']: supplied value or None
PortContext.current['binding:vif_type']: 'unbound'
PortContext.bound_segment: None
PortContext.bound_driver: None

3b) Similarly, in a port update operation on a previously unbound port,
all drivers' port_update_precommit() and port_update_postcommit()
methods will be called, with PortContext properies as shown. If a value
for binding:host_id was supplied, binding will occur afterwards as
described in 4 below.

PortContext.original['binding:host_id']: previous value or None
PortContext.original['binding:vif_type']: 'unbound' or 'binding_failed'
PortContext.original_bound_segment: None
PortContext.original_bound_driver: None
PortContext.current['binding:host_id']: current value or None
PortContext.current['binding:vif_type']: 'unbound'
PortContext.bound_segment: None
PortContext.bound_driver: None

3c) In a port update operation on a previously bound port that does not
trigger unbinding or rebinding, all drivers' update_port_precommit() and
update_port_postcommit() methods will be called with PortContext
properties reflecting unchanged binding states as shown.

PortContext.original['binding:host_id']: previous value
PortContext.original['binding:vif_type']: previous value
PortContext.original_bound_segment: previous value
PortContext.original_bound_driver: previous value
PortContext.current['binding:host_id']: previous value
PortContext.current['binding:vif_type']: previous value
PortContext.bound_segment: previous value
PortContext.bound_driver: previous value

3d) In a the port update operation on a previously bound port that does
trigger unbinding or rebinding, all drivers' update_port_precommit() and
update_port_postcommit() methods will be called with PortContext
properties reflecting the previously bound and currently unbound binding
states as shown. If a value for binding:host_id was supplied, binding
will occur afterwards as described in 4 below.

PortContext.original['binding:host_id']: previous value
PortContext.original['binding:vif_type']: previous value
PortContext.original_bound_segment: previous value
PortContext.original_bound_driver: previous value
PortContext.current['binding:host_id']: new or current value
PortContext.current['binding:vif_type']: 'unbound'