@@ -14,18 +14,17 @@ use crate::params::{
14
14
InstanceHardware , InstanceMigrationSourceParams ,
15
15
InstanceMigrationTargetParams , InstanceStateRequested , VpcFirewallRule ,
16
16
} ;
17
+ use crate :: profile:: * ;
17
18
use anyhow:: anyhow;
18
19
use backoff:: BackoffError ;
19
20
use futures:: lock:: { Mutex , MutexGuard } ;
20
21
use illumos_utils:: dladm:: Etherstub ;
21
22
use illumos_utils:: link:: VnicAllocator ;
22
23
use illumos_utils:: opte:: PortManager ;
23
- use illumos_utils:: running_zone:: {
24
- InstalledZone , RunCommandError , RunningZone ,
25
- } ;
24
+ use illumos_utils:: running_zone:: { InstalledZone , RunningZone } ;
26
25
use illumos_utils:: svc:: wait_for_service;
27
26
use illumos_utils:: zfs:: ZONE_ZFS_RAMDISK_DATASET_MOUNTPOINT ;
28
- use illumos_utils:: zone:: { AddressRequest , PROPOLIS_ZONE_PREFIX } ;
27
+ use illumos_utils:: zone:: PROPOLIS_ZONE_PREFIX ;
29
28
use omicron_common:: address:: NEXUS_INTERNAL_PORT ;
30
29
use omicron_common:: address:: PROPOLIS_PORT ;
31
30
use omicron_common:: api:: internal:: nexus:: InstanceRuntimeState ;
@@ -37,7 +36,7 @@ use omicron_common::backoff;
37
36
use propolis_client:: Client as PropolisClient ;
38
37
use slog:: Logger ;
39
38
use std:: net:: IpAddr ;
40
- use std:: net:: SocketAddr ;
39
+ use std:: net:: { SocketAddr , SocketAddrV6 } ;
41
40
use std:: sync:: Arc ;
42
41
use tokio:: task:: JoinHandle ;
43
42
use uuid:: Uuid ;
@@ -96,6 +95,9 @@ pub enum Error {
96
95
97
96
#[ error( "Instance already registered with Propolis ID {0}" ) ]
98
97
InstanceAlreadyRegistered ( Uuid ) ,
98
+
99
+ #[ error( "I/O error" ) ]
100
+ Io ( #[ from] std:: io:: Error ) ,
99
101
}
100
102
101
103
// Issues read-only, idempotent HTTP requests at propolis until it responds with
@@ -143,12 +145,8 @@ fn service_name() -> &'static str {
143
145
"svc:/system/illumos/propolis-server"
144
146
}
145
147
146
- fn instance_name ( id : & Uuid ) -> String {
147
- format ! ( "vm-{}" , id)
148
- }
149
-
150
- fn fmri_name ( id : & Uuid ) -> String {
151
- format ! ( "{}:{}" , service_name( ) , instance_name( id) )
148
+ fn fmri_name ( ) -> String {
149
+ format ! ( "{}:default" , service_name( ) )
152
150
}
153
151
154
152
fn propolis_zone_name ( id : & Uuid ) -> String {
@@ -673,6 +671,10 @@ impl Instance {
673
671
migration_params : Option < InstanceMigrationTargetParams > ,
674
672
) -> Result < ( ) , Error > {
675
673
if let Some ( running_state) = inner. running_state . as_ref ( ) {
674
+ info ! (
675
+ & inner. log,
676
+ "Ensuring instance which already has a running state"
677
+ ) ;
676
678
inner
677
679
. propolis_ensure (
678
680
& running_state. client ,
@@ -692,10 +694,13 @@ impl Instance {
692
694
// logically running (on the source) while the target Propolis
693
695
// is being launched.
694
696
if migration_params. is_none ( ) {
697
+ info ! ( & inner. log, "Ensuring new instance" ) ;
695
698
inner. state . transition ( PublishedInstanceState :: Starting ) ;
696
699
if let Err ( e) = inner. publish_state_to_nexus ( ) . await {
697
700
break ' setup Err ( e) ;
698
701
}
702
+ } else {
703
+ info ! ( & inner. log, "Ensuring new instance (migration)" ) ;
699
704
}
700
705
701
706
// Set up the Propolis zone and the objects associated with it.
@@ -878,118 +883,53 @@ impl Instance {
878
883
)
879
884
. await ?;
880
885
881
- let running_zone = RunningZone :: boot ( installed_zone) . await ?;
882
- let addr_request = AddressRequest :: new_static ( inner. propolis_ip , None ) ;
883
- let network = running_zone. ensure_address ( addr_request) . await ?;
884
- info ! ( inner. log, "Created address {} for zone: {}" , network, zname) ;
885
-
886
886
let gateway = inner. port_manager . underlay_ip ( ) ;
887
- running_zone. add_default_route ( * gateway) ?;
888
-
889
- // Run Propolis in the Zone.
890
- let smf_service_name = "svc:/system/illumos/propolis-server" ;
891
- let instance_name = format ! ( "vm-{}" , inner. propolis_id( ) ) ;
892
- let smf_instance_name =
893
- format ! ( "{}:{}" , smf_service_name, instance_name) ;
894
- let server_addr = SocketAddr :: new ( inner. propolis_ip , PROPOLIS_PORT ) ;
895
-
896
- // We intentionally do not import the service - it is placed under
897
- // `/var/svc/manifest`, and should automatically be imported by
898
- // configd.
899
- //
900
- // Insteady, we re-try adding the instance until it succeeds.
901
- // This implies that the service was added successfully.
902
- info ! (
903
- inner. log, "Adding service" ; "smf_name" => & smf_instance_name
904
- ) ;
905
- backoff:: retry_notify (
906
- backoff:: retry_policy_local ( ) ,
907
- || async {
908
- running_zone
909
- . run_cmd ( & [
910
- illumos_utils:: zone:: SVCCFG ,
911
- "-s" ,
912
- smf_service_name,
913
- "add" ,
914
- & instance_name,
915
- ] )
916
- . map_err ( |e| backoff:: BackoffError :: transient ( e) )
917
- } ,
918
- |err : RunCommandError , delay| {
919
- warn ! (
920
- inner. log,
921
- "Failed to add {} as a service (retrying in {:?}): {}" ,
922
- instance_name,
923
- delay,
924
- err. to_string( )
925
- ) ;
926
- } ,
927
- )
928
- . await ?;
929
-
930
- info ! ( inner. log, "Adding service property group 'config'" ) ;
931
- running_zone. run_cmd ( & [
932
- illumos_utils:: zone:: SVCCFG ,
933
- "-s" ,
934
- & smf_instance_name,
935
- "addpg" ,
936
- "config" ,
937
- "astring" ,
938
- ] ) ?;
939
-
940
- info ! ( inner. log, "Setting server address property" ; "address" => & server_addr) ;
941
- running_zone. run_cmd ( & [
942
- illumos_utils:: zone:: SVCCFG ,
943
- "-s" ,
944
- & smf_instance_name,
945
- "setprop" ,
946
- & format ! ( "config/server_addr={}" , server_addr) ,
947
- ] ) ?;
948
-
949
- let metric_addr = inner. lazy_nexus_client . get_ip ( ) . await . unwrap ( ) ;
950
- info ! (
951
- inner. log,
952
- "Setting metric address property address [{}]:{}" ,
953
- metric_addr,
887
+ // TODO: We should pass DNS information to Propolis, rather than a
888
+ // single point-in-time Nexus IP address.
889
+ let metric_ip = inner. lazy_nexus_client . get_ip ( ) . await . unwrap ( ) ;
890
+ let metric_addr = SocketAddr :: V6 ( SocketAddrV6 :: new (
891
+ metric_ip,
954
892
NEXUS_INTERNAL_PORT ,
955
- ) ;
956
- running_zone. run_cmd ( & [
957
- illumos_utils:: zone:: SVCCFG ,
958
- "-s" ,
959
- & smf_instance_name,
960
- "setprop" ,
961
- & format ! (
962
- "config/metric_addr=[{}]:{}" ,
963
- metric_addr, NEXUS_INTERNAL_PORT
893
+ 0 ,
894
+ 0 ,
895
+ ) ) ;
896
+
897
+ let config = PropertyGroupBuilder :: new ( "config" )
898
+ . add_property (
899
+ "datalink" ,
900
+ "astring" ,
901
+ installed_zone. get_control_vnic_name ( ) ,
902
+ )
903
+ . add_property ( "gateway" , "astring" , & gateway. to_string ( ) )
904
+ . add_property (
905
+ "listen_addr" ,
906
+ "astring" ,
907
+ & inner. propolis_ip . to_string ( ) ,
908
+ )
909
+ . add_property ( "listen_port" , "astring" , & PROPOLIS_PORT . to_string ( ) )
910
+ . add_property ( "metric_addr" , "astring" , & metric_addr. to_string ( ) ) ;
911
+
912
+ let profile = ProfileBuilder :: new ( "omicron" ) . add_service (
913
+ ServiceBuilder :: new ( "system/illumos/propolis-server" ) . add_instance (
914
+ ServiceInstanceBuilder :: new ( "default" )
915
+ . add_property_group ( config) ,
964
916
) ,
965
- ] ) ?;
966
-
967
- info ! ( inner. log, "Refreshing instance" ) ;
968
- running_zone. run_cmd ( & [
969
- illumos_utils:: zone:: SVCCFG ,
970
- "-s" ,
971
- & smf_instance_name,
972
- "refresh" ,
973
- ] ) ?;
974
-
975
- info ! ( inner. log, "Enabling instance" ) ;
976
- running_zone. run_cmd ( & [
977
- illumos_utils:: zone:: SVCADM ,
978
- "enable" ,
979
- "-t" ,
980
- & smf_instance_name,
981
- ] ) ?;
917
+ ) ;
918
+ profile. add_to_zone ( & inner. log , & installed_zone) . await ?;
982
919
920
+ let running_zone = RunningZone :: boot ( installed_zone) . await ?;
983
921
info ! ( inner. log, "Started propolis in zone: {}" , zname) ;
984
922
985
923
// This isn't strictly necessary - we wait for the HTTP server below -
986
924
// but it helps distinguish "online in SMF" from "responding to HTTP
987
925
// requests".
988
- let fmri = fmri_name ( inner . propolis_id ( ) ) ;
926
+ let fmri = fmri_name ( ) ;
989
927
wait_for_service ( Some ( & zname) , & fmri)
990
928
. await
991
929
. map_err ( |_| Error :: Timeout ( fmri. to_string ( ) ) ) ?;
930
+ info ! ( inner. log, "Propolis SMF service is online" ) ;
992
931
932
+ let server_addr = SocketAddr :: new ( inner. propolis_ip , PROPOLIS_PORT ) ;
993
933
inner. state . current_mut ( ) . propolis_addr = Some ( server_addr) ;
994
934
995
935
// We use a custom client builder here because the default progenitor
@@ -1004,6 +944,7 @@ impl Instance {
1004
944
// yet. Wait for it to respond to requests, so users of the instance
1005
945
// don't need to worry about initialization races.
1006
946
wait_for_http_server ( & inner. log , & client) . await ?;
947
+ info ! ( inner. log, "Propolis HTTP server online" ) ;
1007
948
1008
949
Ok ( PropolisSetup { client, running_zone } )
1009
950
}
0 commit comments