]> xenbits.xen.org Git - xenclient/toolstack.git/commitdiff
Generate MAC/bridge on reading the config file rather than on starting the VM
authorJon Ludlam <Jonathan.Ludlam@eu.citrix.com>
Tue, 25 Aug 2009 12:24:19 +0000 (13:24 +0100)
committerJon Ludlam <Jonathan.Ludlam@eu.citrix.com>
Tue, 25 Aug 2009 12:24:19 +0000 (13:24 +0100)
xenvm/vmact.ml
xenvm/vmconfig.ml
xenvm/xenvm.ml

index 5fe4f118137f8ddb1633156832bc40fe3fdc3993..ad8794e3373aebc346961c552964fc4e9e62225a 100644 (file)
@@ -111,65 +111,9 @@ let add_disk_to_vm ~xs state disk =
        ()
 
 let add_nic_to_vm ~xs state nic =
-       nic.nic_bridge_gen <- (
-               match nic.nic_bridge with
-               | None ->
-                       let l = Netdev.Bridge.list () in
-                       if List.length l > 0 then
-                               List.hd l
-                       else
-                               ""
-               | Some bridge ->
-                       if Netdev.Bridge.exists bridge then
-                               bridge
-                       else
-                               ""
-       );
-       if nic.nic_mac_gen = "" then (
-               let generate_random_mac () =
-                       String.concat ":" (List.map (sprintf "%02x")
-                                       ([0x00; 0x16; 0x3e] @
-                                       List.map Random.int [0x80; 0x100; 0x100]))
-                       in
-               let generate_vm_mac nic_id nic_model vm_uuid =
-                       let s_of_c c1 c2 =
-                               let s = String.create 2 in
-                               s.[0] <- c1; s.[1] <- c2; s
-                               in
-                       let unicast_local h =
-                               let v = int_of_string ("0x" ^ (List.hd h)) in
-                               let n = sprintf "%02x" (0x2 lor (v land 0xfe)) in
-                               n :: (List.tl h)
-                               in
-                       let vector =
-                               (if nic_id = -1 then [] else [ string_of_int nic_id ]) @
-                               (match nic_model with None -> [] | Some x -> [ x ]) @
-                               [ vm_uuid ]
-                               in
-                       let digest = Digest.to_hex (Digest.string (String.concat " " vector)) in
-                       let hexs = List.map (fun i -> s_of_c digest.[i] digest.[i + 12]) [ 0; 2; 1; 7; 6; 4 ] in
-                       String.concat ":" (unicast_local hexs)
-                       in
-               let is_valid_mac s =
-                       let x = String.split ':' s in
-                       if List.length x != 6 then
-                               false
-                       else (
-                               try ignore (List.map (fun s -> int_of_string ("0x" ^ s)) x); true
-                               with _ -> false
-                       )
-                       in
-               nic.nic_mac_gen <- (
-                       match nic.nic_mac with
-                       | Some "random"    -> generate_random_mac ();
-                       | None | Some "vm" -> generate_vm_mac nic.nic_id nic.nic_model state.vm_uuid
-                       | Some mac         ->
-                               if is_valid_mac mac then mac else generate_vm_mac nic.nic_id nic.nic_model state.vm_uuid
-               )
-       );
-       let netty = Netman.Bridge nic.nic_bridge_gen in
+       let netty = Netman.Bridge nic.nic_bridge in
        let (_: Device_common.device) =
-               Device.Vif.add ~xs ~devid:nic.nic_id ~netty ~mac:nic.nic_mac_gen
+               Device.Vif.add ~xs ~devid:nic.nic_id ~netty ~mac:nic.nic_mac
                               ~protocol:(devproto_of_state state) state.vm_domid in
        ()
 
@@ -191,7 +135,7 @@ let get_pcis cfg =
 
 let dm_info_of_cfg cfg =
        let nics = get_nics cfg in
-       let nics = List.map (fun nic -> nic.nic_mac_gen, nic.nic_bridge_gen, nic.nic_model) nics in
+       let nics = List.map (fun nic -> nic.nic_mac, nic.nic_bridge, if nic.nic_model="" then None else Some nic.nic_model) nics in
        let disp =
                match cfg.display with
                | DisplayNone    -> Device.Dm.NONE
@@ -610,7 +554,7 @@ let device_cmd xc xs state ty subcmd args =
        let nic_list args =
                let l = List.map (fun nic ->
                        sprintf "id: %d, bridge:%s, mac:%s\n"
-                               nic.nic_id nic.nic_bridge_gen nic.nic_mac_gen
+                               nic.nic_id nic.nic_bridge nic.nic_mac
                ) cfg.nics in
                Xenvmlib.Msg (String.concat "" l)
                in
@@ -652,7 +596,7 @@ let get_new_config state =
        match state.vm_next_cfg with
        | None -> state.vm_cfg
        | Some cfg -> cfg
-
+           
 let set_new_config state cfg =
        state.vm_next_cfg <- Some cfg
 
@@ -679,13 +623,13 @@ let add_disk state path device ty mode devtype =
        Xenvmlib.Ok
 
 let add_nic state bridge mac model =
-       let nic = { Vmconfig.default_nic with
-               Vmconfig.nic_bridge = bridge;
-               Vmconfig.nic_mac = mac;
-               Vmconfig.nic_model = model;
-       } in
+        let nic = Vmconfig.default_nic in
+       let nic = match bridge with Some x -> {nic with nic_bridge=x} | None -> nic in
+       let nic = match mac with Some x -> {nic with nic_mac=x} | None -> nic in
+       let nic = match model with Some x -> {nic with nic_model=x} | None -> nic in
        let cfg = get_new_config state in
-       let cfg = { cfg with nics = cfg.nics @ [ nic ] } in
+       let nics = Vmconfig.Config.sanitise_nics state.vm_uuid (cfg.nics @ [ nic ]) in
+       let cfg = { cfg with nics = nics } in
        set_new_config state cfg;
        Xenvmlib.Ok
 
index 15a5aa2d8f4a0b9b19c88486698bccbdc5a443f0..d687393480e9147d59eaf56dfd65951e89a3ea28 100644 (file)
@@ -87,11 +87,9 @@ type config_disk = {
 
 type config_nic = {
        nic_id: int;
-       nic_bridge: string option;
-       mutable nic_bridge_gen: string;
-       nic_mac: string option;
-       mutable nic_mac_gen: string;
-       nic_model: string option;
+       nic_bridge: string;
+       nic_mac: string;
+       nic_model: string;
        nic_dynadded: bool;
 }
 
@@ -156,11 +154,9 @@ type config = {
 let default_nic =
        {
                nic_id = -1;
-               nic_bridge = None;
-               nic_bridge_gen = "";
-               nic_mac = None;
-               nic_mac_gen = "";
-               nic_model = None;
+               nic_bridge = "";
+               nic_mac = "";
+               nic_model = "";
                nic_dynadded = false;
        }
 
@@ -212,9 +208,9 @@ let config_nic_of_string s =
        let ls = if s = "" then [] else String.split ',' s in
 
        let id = ref (-1)
-       and bridge = ref None
-       and model = ref None
-       and mac = ref None in
+       and bridge = ref ""
+       and model = ref ""
+       and mac = ref "" in
 
        List.iter (fun v ->
                let lv = String.split '=' v in
@@ -223,9 +219,9 @@ let config_nic_of_string s =
 
                match lvalue with
                | "id"     -> id := int_of_string value
-               | "bridge" -> bridge := Some value
-               | "model"  -> model := Some value
-               | "mac"    -> mac := Some value
+               | "bridge" -> bridge := value
+               | "model"  -> model := value
+               | "mac"    -> mac := value
                | _        -> ()
        ) ls;
 
@@ -236,8 +232,8 @@ let config_nic_of_string s =
                nic_model = !model;
        }
 
-(* Where NIC IDs have been left blank (or explicitly set to -1), here we allocate them a reasonable number *)
-let assign_nic_ids nics =
+(* Where NIC IDs have been left blank (or explicitly set to -1), here we allocate them a reasonable number. We also allocate a bridge and a mac, if necessary *)
+let sanitise_nics vm_uuid nics =
        let sort_nics nics = List.sort (fun nic1 nic2 -> compare nic1.nic_id nic2.nic_id) nics in
        let assert_ok nics =
                ignore(List.fold_left (fun last_id nic -> 
@@ -259,7 +255,69 @@ let assign_nic_ids nics =
        let (assigned,unassigned) = List.partition (fun nic -> nic.nic_id >= 0) nics in
        let nics = List.fold_right allocate_nic_id unassigned (sort_nics assigned) in
        assert_ok nics;
-       nics
+
+       let fix_bridge nic = 
+         {nic with nic_bridge = 
+             match nic.nic_bridge with
+             | "" ->
+                 let l = Netdev.Bridge.list () in
+                 if List.length l > 0 then
+                   List.hd l
+                 else
+                   ""
+             | bridge ->
+                 if Netdev.Bridge.exists bridge then
+                   bridge
+                 else
+                   ""} in
+
+       let nics = List.map fix_bridge nics in
+
+       let fix_mac nic =
+         {nic with nic_mac = 
+             if nic.nic_mac <> "" then nic.nic_mac else (
+               let generate_random_mac () =
+                 String.concat ":" (List.map (sprintf "%02x")
+                                       ([0x00; 0x16; 0x3e] @
+                                           List.map Random.int [0x80; 0x100; 0x100]))
+               in
+               let generate_vm_mac nic_id nic_model vm_uuid =
+                 let s_of_c c1 c2 =
+                   let s = String.create 2 in
+                   s.[0] <- c1; s.[1] <- c2; s
+                 in
+                 let unicast_local h =
+                   let v = int_of_string ("0x" ^ (List.hd h)) in
+                   let n = sprintf "%02x" (0x2 lor (v land 0xfe)) in
+                   n :: (List.tl h)
+                 in
+                 let vector =
+                   (if nic_id = -1 then [] else [ string_of_int nic_id ]) @
+                               (match nic_model with "" -> [] | x -> [ x ]) @
+                     [ vm_uuid ]
+                 in
+                 let digest = Digest.to_hex (Digest.string (String.concat " " vector)) in
+                 let hexs = List.map (fun i -> s_of_c digest.[i] digest.[i + 12]) [ 0; 2; 1; 7; 6; 4 ] in
+                 String.concat ":" (unicast_local hexs)
+               in
+               let is_valid_mac s =
+                 let x = String.split ':' s in
+                 if List.length x != 6 then
+                   false
+                 else (
+                   try ignore (List.map (fun s -> int_of_string ("0x" ^ s)) x); true
+                   with _ -> false
+                 )
+               in
+               match nic.nic_mac with
+                 | "random"    -> generate_random_mac ();
+                 | "" | "vm" -> generate_vm_mac nic.nic_id nic.nic_model vm_uuid
+                 | mac         ->
+                     if is_valid_mac mac then mac else generate_vm_mac nic.nic_id nic.nic_model vm_uuid
+             )
+         }
+       in
+       List.map fix_mac nics
                
 let config_disk_of_string s =
        (* physpath:phystype:virtpath:mode:devtype *)
@@ -588,7 +646,7 @@ let of_file uuid error_report file =
                Config.Error ls -> error_report ls
        end;
 
-       let nics = assign_nic_ids !cfg.nics in
+       let nics = sanitise_nics uuid !cfg.nics in
 
        { !cfg with
                __uuid = !__uuid;
index 32e0a3a0f52977efa1cdd7e190167ac710317c5e..989193cf580773ff7e32382a6f7a728aa8d7957c 100644 (file)
@@ -289,8 +289,8 @@ let monitor_vm state =
                        let online = Hotplug.device_is_online ~xs device in
                        let connected = Hotplug.device_is_connected ~xs device in
                        if online && not connected  then (
-                               let netty = Netman.Bridge nic.nic_bridge_gen in
-                               let mac = nic.nic_mac_gen in
+                               let netty = Netman.Bridge nic.nic_bridge in
+                               let mac = nic.nic_mac in
                                let protocol = Vmact.devproto_of_state state in
                                let (_: Device_common.device) = Device.Vif.plug ~xs ~netty ~mac ~protocol device in
                                ()