# HG changeset patch # User Rob Hoes # Date 1278673892 -3600 # Node ID 809cd814d9404bb4109719fd8d1b4b81395318a9 # Parent 1c34e2bd452112970632c09eaa52346e778f3d14 Tunnelling: do not allow transport PIFs to be destroyed Signed-off-by: Rob Hoes diff -r 1c34e2bd4521 -r 809cd814d940 ocaml/idl/api_errors.ml --- a/ocaml/idl/api_errors.ml +++ b/ocaml/idl/api_errors.ml @@ -104,6 +104,7 @@ let openvswitch_not_active = "OPENVSWITCH_NOT_ACTIVE" let transport_pif_not_configured = "TRANSPORT_PIF_NOT_CONFIGURED" let is_tunnel_access_pif = "IS_TUNNEL_ACCESS_PIF" +let pif_tunnel_still_exists = "PIF_TUNNEL_STILL_EXISTS" let vlan_tag_invalid = "VLAN_TAG_INVALID" let vm_bad_power_state = "VM_BAD_POWER_STATE" diff -r 1c34e2bd4521 -r 809cd814d940 ocaml/idl/datamodel.ml --- a/ocaml/idl/datamodel.ml +++ b/ocaml/idl/datamodel.ml @@ -445,6 +445,8 @@ ~doc:"The tunnel transport PIF has no IP configuration set." (); error Api_errors.is_tunnel_access_pif ["PIF"] ~doc:"You tried to create a VLAN or tunnel on top of a tunnel access PIF - use the underlying transport PIF instead." (); + error Api_errors.pif_tunnel_still_exists ["PIF"] + ~doc:"Operation cannot proceed while a tunnel exists on this interface." (); (* VM specific errors *) error Api_errors.vm_is_protected [ "vm" ] @@ -3871,6 +3873,7 @@ ~params:[Ref _pif, "self", "the PIF object to plug"] ~in_product_since:rel_miami ~allowed_roles:_R_POOL_OP + ~errs:[Api_errors.transport_pif_not_configured] () let pif_unplug = call @@ -3926,6 +3929,7 @@ ~params:[Ref _pif, "self", "The PIF object to destroy"] ~in_product_since:rel_miami ~allowed_roles:_R_POOL_OP + ~errs:[Api_errors.pif_tunnel_still_exists] () let pif_introduce_params first_rel = diff -r 1c34e2bd4521 -r 809cd814d940 ocaml/xapi/xapi_pif.ml --- a/ocaml/xapi/xapi_pif.ml +++ b/ocaml/xapi/xapi_pif.ml @@ -49,6 +49,20 @@ if Db.PIF.get_VLAN ~__context ~self <> (-1L) && not (Xapi_fist.allow_forget_of_vlan_pif ()) then raise (Api_errors.Server_error (Api_errors.pif_vlan_still_exists, [ Ref.string_of self ])) +let assert_no_tunnels ~__context ~self = + (* Disallow if this is a transport interface of any existing tunnel *) + let tunnels = Db.PIF.get_tunnel_transport_PIF_of ~__context ~self in + debug "PIF %s assert_no_tunnels = [ %s ]" + (Db.PIF.get_uuid ~__context ~self) (String.concat "; " (List.map Ref.string_of tunnels)); + if tunnels <> [] then begin + debug "PIF has associated tunnels: [ %s ]" + (String.concat "; " (List.map (fun self -> Db.Tunnel.get_uuid ~__context ~self) tunnels)); + raise (Api_errors.Server_error (Api_errors.pif_tunnel_still_exists, [ Ref.string_of self ])) + end; + (* Disallow if this is an access interface of a tunnel *) + if Db.PIF.get_tunnel_access_PIF_of ~__context ~self <> [] + then raise (Api_errors.Server_error (Api_errors.pif_tunnel_still_exists, [ Ref.string_of self ])) + let assert_not_management_pif ~__context ~self = if Db.PIF.get_currently_attached ~__context ~self && Db.PIF.get_management ~__context ~self then @@ -259,6 +273,7 @@ let forget ~__context ~self = assert_not_in_bond ~__context ~self; assert_no_vlans ~__context ~self; + assert_no_tunnels ~__context ~self; assert_not_slave_management_pif ~__context ~self; assert_no_protection_enabled ~__context ~self;