@@ -1347,13 +1347,28 @@ module HostsConfFunc (T : LocalHostTag) : HostsConf = struct
13471347 let name = String. lowercase_ascii name in
13481348 let domain = String. lowercase_ascii domain in
13491349 let fqdn = Printf. sprintf " %s.%s" name domain in
1350+ let rec add_hostname pre line =
1351+ match line with
1352+ | ip :: alias when ip = T. local_ip ->
1353+ (* Add localhost IP *)
1354+ add_hostname [ip] alias
1355+ | sp :: left when sp = " " ->
1356+ (* Add space to reserve the indent *)
1357+ add_hostname (pre @ [sp]) left
1358+ | alias :: left ->
1359+ (* hosts entry: ip fqdn alias1 alias2 ... *)
1360+ pre @ [fqdn; name; alias] @ left
1361+ | _ ->
1362+ failwith " Can not add local hostname to non local IP"
1363+ in
1364+
13501365 match interest line with
13511366 | false ->
13521367 line
13531368 | true ->
13541369 String. split_on_char sep line
13551370 |> List. filter (fun x -> x <> name && x <> fqdn)
1356- |> (fun x -> match op with Add -> x @ [name; fqdn] | Remove -> x)
1371+ |> (fun x -> match op with Add -> add_hostname [] x | Remove -> x)
13571372 |> String. concat sep_str
13581373
13591374 let leave ~name ~domain ~lines =
@@ -1369,8 +1384,8 @@ module HostsConfFunc (T : LocalHostTag) : HostsConf = struct
13691384 | false ->
13701385 (* Does not found and updated the conf, then add one *)
13711386 [
1372- Printf. sprintf " %s%s%s%s%s. %s" T. local_ip sep_str name sep_str name
1373- domain
1387+ Printf. sprintf " %s%s%s. %s%s%s" T. local_ip sep_str name domain sep_str
1388+ name
13741389 ]
13751390 @ x
13761391end
@@ -1386,18 +1401,91 @@ module ConfigHosts = struct
13861401 let join ~name ~domain =
13871402 read_lines ~path |> fun lines ->
13881403 HostsConfIPv4. join ~name ~domain ~lines |> fun lines ->
1389- HostsConfIPv6. join ~name ~domain ~lines
1404+ HostsConfIPv6. join ~name ~domain ~lines |> fun x ->
1405+ x @ [" " ] (* Add final line break *)
13901406 |> String. concat " \n "
13911407 |> write_string_to_file path
13921408
13931409 let leave ~name ~domain =
13941410 read_lines ~path |> fun lines ->
13951411 HostsConfIPv4. leave ~name ~domain ~lines |> fun lines ->
1396- HostsConfIPv6. leave ~name ~domain ~lines
1412+ HostsConfIPv6. leave ~name ~domain ~lines |> fun x ->
1413+ x @ [" " ] (* Add final line break *)
13971414 |> String. concat " \n "
13981415 |> write_string_to_file path
13991416end
14001417
1418+ module ResolveConfig = struct
1419+ open Xapi_stdext_unix.Unixext
1420+
1421+ let path = " /etc/resolv.conf"
1422+
1423+ type t = Add | Remove
1424+
1425+ let handle op domain =
1426+ let config = Printf. sprintf " search %s" domain in
1427+ read_lines ~path |> List. filter (fun x -> x <> config) |> fun x ->
1428+ (match op with Add -> config :: x | Remove -> x) |> fun x ->
1429+ x @ [" " ] |> String. concat " \n " |> write_string_to_file path
1430+
1431+ let join ~domain = handle Add domain
1432+
1433+ let leave ~domain = handle Remove domain
1434+ end
1435+
1436+ module DNSSync = struct
1437+ let task_name = " Sync hostname with DNS"
1438+
1439+ type t = Register | Unregister
1440+
1441+ let handle op hostname netbios_name domain =
1442+ (* By default, hostname should equal to netbios_name, just register it to DNS server*)
1443+ try
1444+ let ops =
1445+ match op with Register -> " register" | Unregister -> " unregister"
1446+ in
1447+ let netbios_fqdn = Printf. sprintf " %s.%s" netbios_name domain in
1448+ let args = [" ads" ; " dns" ] @ [ops] @ [" --machine-pass" ] in
1449+ Helpers. call_script net_cmd (args @ [netbios_fqdn]) |> ignore ;
1450+ if hostname <> netbios_name then
1451+ let hostname_fqdn = Printf. sprintf " %s.%s" hostname domain in
1452+ (* netbios_name is compressed, op on extra hostname *)
1453+ Helpers. call_script net_cmd (args @ [hostname_fqdn]) |> ignore
1454+ with e ->
1455+ debug " Register/unregister with DNS failed %s" (ExnHelper. string_of_exn e)
1456+
1457+ let register hostname netbios_name domain =
1458+ handle Register hostname netbios_name domain
1459+
1460+ let unregister hostname netbios_name domain =
1461+ handle Unregister hostname netbios_name domain
1462+
1463+ let sync () =
1464+ Server_helpers. exec_with_new_task " sync hostname with DNS"
1465+ @@ fun __context ->
1466+ let host = Helpers. get_localhost ~__context in
1467+ let service_name =
1468+ Db.Host. get_external_auth_service_name ~__context ~self: host
1469+ in
1470+ let netbios_name =
1471+ Db.Host. get_external_auth_configuration ~__context ~self: host
1472+ |> fun config -> List. assoc_opt " netbios_name" config
1473+ in
1474+ let hostname = Db.Host. get_hostname ~__context ~self: host in
1475+ match netbios_name with
1476+ | Some netbios ->
1477+ register hostname netbios service_name
1478+ | None ->
1479+ debug " Netbios name is none, skip sync hostname to DNS"
1480+
1481+ let trigger_sync ~start =
1482+ debug " Trigger task: %s" task_name ;
1483+ Scheduler. add_to_queue task_name
1484+ (Scheduler. Periodic ! Xapi_globs. winbind_dns_sync_interval) start sync
1485+
1486+ let stop_sync () = Scheduler. remove_from_queue task_name
1487+ end
1488+
14011489let build_netbios_name ~config_params =
14021490 let key = " netbios-name" in
14031491 match List. assoc_opt key config_params with
@@ -1721,20 +1809,24 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
17211809 ClosestKdc. trigger_update ~start: 0. ;
17221810 RotateMachinePassword. trigger_rotate ~start: 0. ;
17231811 ConfigHosts. join ~domain: service_name ~name: netbios_name ;
1812+ ResolveConfig. join ~domain: service_name ;
1813+ DNSSync. trigger_sync ~start: 0. ;
17241814 Winbind. set_machine_account_encryption_type netbios_name ;
17251815 debug " Succeed to join domain %s" service_name
17261816 with
17271817 | Forkhelpers. Spawn_internal_error (_ , stdout , _ ) ->
17281818 error " Join domain: %s error: %s" service_name stdout ;
17291819 clear_winbind_config () ;
17301820 ConfigHosts. leave ~domain: service_name ~name: netbios_name ;
1821+ ResolveConfig. leave ~domain: service_name ;
17311822 (* The configure is kept for debug purpose with max level *)
17321823 raise (Auth_service_error (stdout |> tag_from_err_msg, stdout))
17331824 | Xapi_systemctl. Systemctl_fail _ ->
17341825 let msg = Printf. sprintf " Failed to start %s" Winbind. name in
17351826 error " Start daemon error: %s" msg ;
17361827 config_winbind_daemon ~domain: None ~workgroup: None ~netbios_name: None ;
17371828 ConfigHosts. leave ~domain: service_name ~name: netbios_name ;
1829+ ResolveConfig. leave ~domain: service_name ;
17381830 raise (Auth_service_error (E_GENERIC , msg))
17391831 | e ->
17401832 let msg =
@@ -1746,6 +1838,7 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
17461838 error " Enable extauth error: %s" msg ;
17471839 clear_winbind_config () ;
17481840 ConfigHosts. leave ~domain: service_name ~name: netbios_name ;
1841+ ResolveConfig. leave ~domain: service_name ;
17491842 raise (Auth_service_error (E_GENERIC , msg))
17501843
17511844 (* unit on_disable()
@@ -1760,9 +1853,13 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
17601853 let user = List. assoc_opt " user" config_params in
17611854 let pass = List. assoc_opt " pass" config_params in
17621855 let {service_name; netbios_name; _} = get_domain_info_from_db () in
1856+ ResolveConfig. leave ~domain: service_name ;
1857+ DNSSync. stop_sync () ;
17631858 ( match netbios_name with
1764- | Some name ->
1765- ConfigHosts. leave ~domain: service_name ~name
1859+ | Some netbios ->
1860+ ConfigHosts. leave ~domain: service_name ~name: netbios ;
1861+ let hostname = get_localhost_name () in
1862+ DNSSync. unregister hostname netbios service_name
17661863 | _ ->
17671864 ()
17681865 ) ;
@@ -1792,6 +1889,7 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
17921889 ClosestKdc. trigger_update ~start: ClosestKdc. startup_delay ;
17931890 RotateMachinePassword. trigger_rotate ~start: 5. ;
17941891 Winbind. check_ready_to_serve ~timeout: 300. ;
1892+ DNSSync. trigger_sync ~start: 5. ;
17951893
17961894 let {service_name; netbios_name; _} = get_domain_info_from_db () in
17971895 match netbios_name with
0 commit comments