@@ -1548,20 +1548,9 @@ func networkLeasesGet(d *Daemon, r *http.Request) response.Response {
15481548 return response .SyncResponse (true , leases )
15491549}
15501550
1551- func networkStartup (s * state.State ) error {
1551+ func networkStartup (stateFunc func () * state.State ) error {
15521552 var err error
15531553
1554- // Get a list of projects.
1555- var projectNames []string
1556-
1557- err = s .DB .Cluster .Transaction (context .TODO (), func (ctx context.Context , tx * db.ClusterTx ) error {
1558- projectNames , err = dbCluster .GetProjectNames (ctx , tx .Tx ())
1559- return err
1560- })
1561- if err != nil {
1562- return fmt .Errorf ("Failed to load projects: %w" , err )
1563- }
1564-
15651554 // Build a list of networks to initialise, keyed by project and network name.
15661555 const networkPriorityStandalone = 0 // Start networks not dependent on any other network first.
15671556 const networkPriorityPhysical = 1 // Start networks dependent on physical interfaces second.
@@ -1572,38 +1561,14 @@ func networkStartup(s *state.State) error {
15721561 networkPriorityLogical : make (map [network.ProjectNetwork ]struct {}),
15731562 }
15741563
1575- err = s .DB .Cluster .Transaction (context .TODO (), func (ctx context.Context , tx * db.ClusterTx ) error {
1576- for _ , projectName := range projectNames {
1577- networkNames , err := tx .GetCreatedNetworkNamesByProject (ctx , projectName )
1578- if err != nil {
1579- return fmt .Errorf ("Failed to load networks for project %q: %w" , projectName , err )
1580- }
1581-
1582- for _ , networkName := range networkNames {
1583- pn := network.ProjectNetwork {
1584- ProjectName : projectName ,
1585- NetworkName : networkName ,
1586- }
1587-
1588- // Assume all networks are networkPriorityStandalone initially.
1589- initNetworks [networkPriorityStandalone ][pn ] = struct {}{}
1590- }
1591- }
1592-
1593- return nil
1594- })
1595- if err != nil {
1596- return err
1597- }
1598-
15991564 loadedNetworks := make (map [network.ProjectNetwork ]network.Network )
16001565
1601- initNetwork := func (n network.Network , priority int ) error {
1566+ initNetwork := func (s * state. State , n network.Network , priority int ) error {
16021567 err = n .Start ()
16031568 if err != nil {
16041569 err = fmt .Errorf ("Failed starting: %w" , err )
16051570
1606- _ = s .DB .Cluster .Transaction (context .TODO (), func (ctx context.Context , tx * db.ClusterTx ) error {
1571+ _ = s .DB .Cluster .Transaction (context .Background (), func (ctx context.Context , tx * db.ClusterTx ) error {
16071572 return tx .UpsertWarningLocalNode (ctx , n .Project (), entity .TypeNetwork , int (n .ID ()), warningtype .NetworkUnvailable , err .Error ())
16081573 })
16091574
@@ -1625,7 +1590,7 @@ func networkStartup(s *state.State) error {
16251590 return nil
16261591 }
16271592
1628- loadAndInitNetwork := func (pn network.ProjectNetwork , priority int , firstPass bool ) error {
1593+ loadAndInitNetwork := func (s * state. State , pn network.ProjectNetwork , priority int , firstPass bool ) error {
16291594 var err error
16301595 var n network.Network
16311596
@@ -1670,39 +1635,78 @@ func networkStartup(s *state.State) error {
16701635 return nil
16711636 }
16721637
1673- err = initNetwork (n , priority )
1638+ err = initNetwork (s , n , priority )
16741639 if err != nil {
16751640 return err
16761641 }
16771642
16781643 return nil
16791644 }
16801645
1681- // Try initializing networks in priority order.
1682- for priority := range initNetworks {
1683- for pn := range initNetworks [priority ] {
1684- err := loadAndInitNetwork (pn , priority , true )
1646+ remainingNetworksCount := func () int {
1647+ remainingNetworks := 0
1648+ for _ , projectNetworks := range initNetworks {
1649+ remainingNetworks += len (projectNetworks )
1650+ }
1651+
1652+ return remainingNetworks
1653+ }
1654+
1655+ {
1656+ // Peform first pass to start networks.
1657+ // Local scope for state variable during initial pass of setting up networks.
1658+ s := stateFunc ()
1659+ err = s .DB .Cluster .Transaction (s .ShutdownCtx , func (ctx context.Context , tx * db.ClusterTx ) error {
1660+ projectNames , err := dbCluster .GetProjectNames (ctx , tx .Tx ())
16851661 if err != nil {
1686- logger .Error ("Failed initializing network" , logger.Ctx {"project" : pn .ProjectName , "network" : pn .NetworkName , "err" : err })
1662+ return fmt .Errorf ("Failed to load projects: %w" , err )
1663+ }
16871664
1688- continue
1665+ for _ , projectName := range projectNames {
1666+ networkNames , err := tx .GetCreatedNetworkNamesByProject (ctx , projectName )
1667+ if err != nil {
1668+ return fmt .Errorf ("Failed to load networks for project %q: %w" , projectName , err )
1669+ }
1670+
1671+ for _ , networkName := range networkNames {
1672+ pn := network.ProjectNetwork {
1673+ ProjectName : projectName ,
1674+ NetworkName : networkName ,
1675+ }
1676+
1677+ // Assume all networks are networkPriorityStandalone initially.
1678+ initNetworks [networkPriorityStandalone ][pn ] = struct {}{}
1679+ }
16891680 }
1681+
1682+ return nil
1683+ })
1684+ if err != nil {
1685+ return err
16901686 }
1691- }
16921687
1693- loadedNetworks = nil // Don't store loaded networks after first pass.
1688+ // Try initializing networks in priority order.
1689+ for priority := range initNetworks {
1690+ for pn := range initNetworks [priority ] {
1691+ err := loadAndInitNetwork (s , pn , priority , true )
1692+ if err != nil {
1693+ logger .Error ("Failed initializing network" , logger.Ctx {"project" : pn .ProjectName , "network" : pn .NetworkName , "err" : err })
16941694
1695- remainingNetworks := 0
1696- for _ , networks := range initNetworks {
1697- remainingNetworks += len (networks )
1695+ continue
1696+ }
1697+ }
1698+ }
1699+
1700+ loadedNetworks = nil // Don't store loaded networks after first pass.
16981701 }
16991702
17001703 // For any remaining networks that were not successfully initialised, we now start a go routine to
17011704 // periodically try to initialize them again in the background.
1702- if remainingNetworks > 0 {
1705+ if remainingNetworksCount () > 0 {
17031706 go func () {
17041707 for {
17051708 t := time .NewTimer (time .Duration (time .Minute ))
1709+ s := stateFunc () // Get fresh state in case global config has been updated.
17061710
17071711 select {
17081712 case <- s .ShutdownCtx .Done ():
@@ -1716,7 +1720,7 @@ func networkStartup(s *state.State) error {
17161720 // Try initializing networks in priority order.
17171721 for priority := range initNetworks {
17181722 for pn := range initNetworks [priority ] {
1719- err := loadAndInitNetwork (pn , priority , false )
1723+ err := loadAndInitNetwork (s , pn , priority , false )
17201724 if err != nil {
17211725 logger .Error ("Failed initializing network" , logger.Ctx {"project" : pn .ProjectName , "network" : pn .NetworkName , "err" : err })
17221726
@@ -1727,11 +1731,7 @@ func networkStartup(s *state.State) error {
17271731 }
17281732 }
17291733
1730- remainingNetworks := 0
1731- for _ , networks := range initNetworks {
1732- remainingNetworks += len (networks )
1733- }
1734-
1734+ remainingNetworks := remainingNetworksCount ()
17351735 if remainingNetworks <= 0 {
17361736 logger .Info ("All networks initialized" )
17371737 }
0 commit comments