]> xenbits.xen.org Git - xenclient/toolstack.git/commitdiff
[xenvm] Track NetworkManager connection status & delegate to guest
authorTomasz Wroblewski <tomasz.wroblewski@citrix.com>
Tue, 19 Jan 2010 17:32:13 +0000 (17:32 +0000)
committerTomasz Wroblewski <tomasz.wroblewski@citrix.com>
Tue, 19 Jan 2010 17:32:13 +0000 (17:32 +0000)
libs/stdext/stringext.ml
libs/stdext/stringext.mli
xenvm/Makefile
xenvm/network_manager.ml [new file with mode: 0644]
xenvm/xenvm.ml

index 37fb89fc9ce906d3e453dfbaa13786a21aaa15f1..e705be366a7edfe45f0363b15c237115bd22bcd4 100644 (file)
@@ -194,4 +194,13 @@ let map_unlikely s f =
        ) else
                s
 
+let left s n =
+       let l = String.length s in
+       let n = min n l in
+       String.sub s 0 n
+
+let right s n =
+       let l = String.length s in
+       let p = max 0 (l - n) in
+       String.sub s p (l - p)
 end
index 8034c0d3266fade5e0965a6c84c2a38fb106b18a..4383fd54de59a0906b5bd23e011f6d34e8dfecd3 100644 (file)
@@ -99,4 +99,10 @@ module String :
 
     (** map a string trying to fill the buffer by chunk *)
     val map_unlikely : string -> (char -> string option) -> string
+
+    (** get beginning portion of string *)
+    val left : string -> int -> string
+
+    (** get end portion of string *)
+    val right : string -> int -> string
   end
index ab637694d1973e1399929cef5cb4ef986a5bb76c..d868106525a4f79ae87e50ed028f0aab494109bf 100644 (file)
@@ -16,7 +16,7 @@ OCAMLOPTFLAGS += -thread
 #      balloon device_common hotplug device \
 #      domain
 
-xenvm_OBJS = $(TOPLEVEL)/common/config xenvmlib tasks misc vmconfig vmstate vmact xenvm
+xenvm_OBJS = $(TOPLEVEL)/common/config xenvmlib tasks misc vmconfig vmstate vmact network_manager xenvm
 xenvm-cmd_OBJS = xenvmlib xenvm_cmd
 xenops_OBJS = xenops
 
diff --git a/xenvm/network_manager.ml b/xenvm/network_manager.ml
new file mode 100644 (file)
index 0000000..117a6d2
--- /dev/null
@@ -0,0 +1,95 @@
+open Vmstate
+
+module D=Debug.Debugger(struct let name="xenvm" end)
+open D
+
+type devstate =
+       NM_DEVICE_STATE_UNKNOWN
+      | NM_DEVICE_STATE_UNMANAGED
+      | NM_DEVICE_STATE_UNAVAILABLE
+      | NM_DEVICE_STATE_DISCONNECTED
+      | NM_DEVICE_STATE_PREPARE
+      | NM_DEVICE_STATE_CONFIG
+      | NM_DEVICE_STATE_NEED_AUTH
+      | NM_DEVICE_STATE_IP_CONFIG
+      | NM_DEVICE_STATE_ACTIVATED
+      | NM_DEVICE_STATE_FAILED
+
+let devstate_of_int = function
+      | 1 -> NM_DEVICE_STATE_UNMANAGED
+      | 2 -> NM_DEVICE_STATE_UNAVAILABLE
+      | 3 -> NM_DEVICE_STATE_DISCONNECTED
+      | 4 -> NM_DEVICE_STATE_PREPARE
+      | 5 -> NM_DEVICE_STATE_CONFIG
+      | 6 -> NM_DEVICE_STATE_NEED_AUTH
+      | 7 -> NM_DEVICE_STATE_IP_CONFIG
+      | 8 -> NM_DEVICE_STATE_ACTIVATED
+      | 9 -> NM_DEVICE_STATE_FAILED
+      | _ -> NM_DEVICE_STATE_UNKNOWN
+
+let get_devstate bus path =
+       let call = DBus.Message.new_method_call 
+                       "org.freedesktop.NetworkManager" path "org.freedesktop.DBus.Properties" "Get" in
+       DBus.Message.append call [DBus.String "org.freedesktop.NetworkManager.Device";
+                                 DBus.String "State"];
+       let resp = DBus.Connection.send_with_reply_and_block bus call (-1) in
+       match DBus.Message.get_type resp with
+       | DBus.Message.Method_return ->
+                 (match DBus.Message.get resp with
+                 | [DBus.Variant (DBus.UInt32 state)] ->
+                           devstate_of_int (Int32.to_int state)
+                 | _ -> failwith "Unexpected response")
+       | _ -> failwith "Failed to get device state"
+
+let get_devintf bus path =
+       let call = DBus.Message.new_method_call 
+                       "org.freedesktop.NetworkManager" path "org.freedesktop.DBus.Properties" "Get" in
+       DBus.Message.append call [DBus.String "org.freedesktop.NetworkManager.Device";
+                                 DBus.String "Interface"];
+       let resp = DBus.Connection.send_with_reply_and_block bus call (-1) in
+       match DBus.Message.get_type resp with
+       | DBus.Message.Method_return ->
+                 (match DBus.Message.get resp with
+                 | [DBus.Variant (DBus.String intf)] ->
+                           intf
+                 | _ -> failwith "Unexpected response")
+       | _ -> failwith "Failed to get interface name"
+
+let when_conn_changed xs state nic_id news olds =
+       if news <> olds then (
+               let xsnode = Printf.sprintf "/local/domain/%d/device/vif/%d/disconnect" state.vm_domid nic_id in
+               match news, olds with
+               | NM_DEVICE_STATE_ACTIVATED, _ ->
+                         info "Detected active net connection (NetworkManager) for id %d" nic_id;
+                         xs.Xs.write xsnode "0";
+               | _, NM_DEVICE_STATE_ACTIVATED ->
+                         info "Detected inactive net connection (NetworkManager) for id %d" nic_id;
+                         xs.Xs.write xsnode "1";
+               | _ -> ()
+        )
+       
+let process_signal state xs bus msg =
+       let interface = match DBus.Message.get_interface msg with None -> "" | Some i -> i in
+       let member    = match DBus.Message.get_member msg    with None -> "" | Some m -> m in
+       let path      = match DBus.Message.get_path msg      with None -> "" | Some p -> p in
+       let params    = DBus.Message.get msg in
+       match interface, member, params with
+       | "org.freedesktop.NetworkManager.Device",
+         "StateChanged",
+         [DBus.UInt32 news; DBus.UInt32 olds; DBus.UInt32 reason] ->
+                 (* new state *)
+                 let news = devstate_of_int (Int32.to_int news) in
+                 (* previous state *)
+                 let olds = devstate_of_int (Int32.to_int olds) in
+                 (* to keep it simple we look the nic by bridge name.. *)
+                 let bridge = get_devintf bus path in
+                 let nics = List.filter (fun n -> n.ns_bridge = bridge) state.vm_nics in
+                 (match nics with
+                 | [nic] -> 
+                           let id = nic.ns_id in
+                           when_conn_changed xs state id news olds
+                 | _     ->
+                           ()
+                 )
+       | _ -> ()
+                         
index b31df632ad8344e182075cd35bcce6b2bea64856..066c97c74e1deb33c74573d895d95c3fc7a45bee 100644 (file)
@@ -748,6 +748,9 @@ let monitor_rpc_dbus state =
        | _                     -> failwith (Printf.sprintf "cannot grab dbus intf %s" intf)
        );
        (*DBus.Bus.add_match bus match_s false;*)
+       (* listen to Network Manager notificatons *)
+       DBus.Bus.add_match bus "type='signal',interface='org.freedesktop.NetworkManager.Device'" false;
+
        DBus.Connection.flush bus;
 
        let outgoing_mutex = Mutex.create () in
@@ -814,6 +817,10 @@ let monitor_rpc_dbus state =
                                      "expecting string method followed by dictionnary" in
                        Some (err_msg)
                in
+       let process_signal msg =
+               (* handle network manager signals *)
+               with_xs (fun xs -> Network_manager.process_signal state xs bus msg)
+       in
        let process_message msg =
                let ty = DBus.Message.get_type msg in
                match ty with
@@ -824,6 +831,7 @@ let monitor_rpc_dbus state =
                | DBus.Message.Method_call ->
                        process_method_call msg
                | DBus.Message.Signal ->
+                       process_signal msg;
                        None
                | _ ->
                        info "unknown dbus message %s" (DBus.Message.string_of_message_ty ty);