Skip to content

Commit

Permalink
Merge pull request #20056 from Luap99/fast-net-ls
Browse files Browse the repository at this point in the history
compat API: speed up network list
  • Loading branch information
openshift-merge-robot authored Sep 20, 2023
2 parents 93623fe + 8e5adde commit c5be3ae
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 48 deletions.
32 changes: 15 additions & 17 deletions libpod/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -1220,23 +1220,6 @@ func (c *Container) HostNetwork() bool {
return true
}

// ContainerState returns containerstate struct
func (c *Container) ContainerState() (*ContainerState, error) {
if !c.batched {
c.lock.Lock()
defer c.lock.Unlock()

if err := c.syncContainer(); err != nil {
return nil, err
}
}
returnConfig := new(ContainerState)
if err := JSONDeepCopy(c.state, returnConfig); err != nil {
return nil, fmt.Errorf("copying container %s state: %w", c.ID(), err)
}
return c.state, nil
}

// HasHealthCheck returns bool as to whether there is a health check
// defined for the container
func (c *Container) HasHealthCheck() bool {
Expand Down Expand Up @@ -1356,6 +1339,21 @@ func (d ContainerNetworkDescriptions) getInterfaceByName(networkName string) (st
return fmt.Sprintf("eth%d", val), exists
}

// GetNetworkStatus returns the current network status for this container.
// This returns a map without deep copying which means this should only ever
// be used as read only access, do not modify this status.
func (c *Container) GetNetworkStatus() (map[string]types.StatusBlock, error) {
if !c.batched {
c.lock.Lock()
defer c.lock.Unlock()

if err := c.syncContainer(); err != nil {
return nil, err
}
}
return c.getNetworkStatus(), nil
}

// getNetworkStatus get the current network status from the state. If the container
// still uses the old network status it is converted to the new format. This function
// should be used instead of reading c.state.NetworkStatus directly.
Expand Down
90 changes: 59 additions & 31 deletions pkg/api/handlers/compat/networks.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,36 @@ import (
"github.com/sirupsen/logrus"
)

type containerNetStatus struct {
name string
id string
status map[string]nettypes.StatusBlock
}

func getContainerNetStatuses(rt *libpod.Runtime) ([]containerNetStatus, error) {
cons, err := rt.GetAllContainers()
if err != nil {
return nil, err
}
statuses := make([]containerNetStatus, 0, len(cons))
for _, con := range cons {
status, err := con.GetNetworkStatus()
if err != nil {
if errors.Is(err, define.ErrNoSuchCtr) || errors.Is(err, define.ErrCtrRemoved) {
continue
}
return nil, err
}

statuses = append(statuses, containerNetStatus{
id: con.ID(),
name: con.Name(),
status: status,
})
}
return statuses, nil
}

func normalizeNetworkName(rt *libpod.Runtime, name string) (string, bool) {
if name == nettypes.BridgeNetworkDriver {
return rt.Network().DefaultNetworkName(), true
Expand Down Expand Up @@ -56,45 +86,42 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
utils.NetworkNotFound(w, name, err)
return
}
report, err := convertLibpodNetworktoDockerNetwork(runtime, &net, changed)
statuses, err := getContainerNetStatuses(runtime)
if err != nil {
utils.InternalServerError(w, err)
return
}
report := convertLibpodNetworktoDockerNetwork(runtime, statuses, &net, changed)
utils.WriteResponse(w, http.StatusOK, report)
}

func convertLibpodNetworktoDockerNetwork(runtime *libpod.Runtime, network *nettypes.Network, changeDefaultName bool) (*types.NetworkResource, error) {
cons, err := runtime.GetAllContainers()
if err != nil {
return nil, err
}
containerEndpoints := make(map[string]types.EndpointResource, len(cons))
for _, con := range cons {
data, err := con.Inspect(false)
if err != nil {
if errors.Is(err, define.ErrNoSuchCtr) || errors.Is(err, define.ErrCtrRemoved) {
continue
}
return nil, err
}
if netData, ok := data.NetworkSettings.Networks[network.Name]; ok {
func convertLibpodNetworktoDockerNetwork(runtime *libpod.Runtime, statuses []containerNetStatus, network *nettypes.Network, changeDefaultName bool) *types.NetworkResource {
containerEndpoints := make(map[string]types.EndpointResource, len(statuses))
for _, st := range statuses {
if netData, ok := st.status[network.Name]; ok {
ipv4Address := ""
if netData.IPAddress != "" {
ipv4Address = fmt.Sprintf("%s/%d", netData.IPAddress, netData.IPPrefixLen)
}
ipv6Address := ""
if netData.GlobalIPv6Address != "" {
ipv6Address = fmt.Sprintf("%s/%d", netData.GlobalIPv6Address, netData.GlobalIPv6PrefixLen)
macAddr := ""
for _, dev := range netData.Interfaces {
for _, subnet := range dev.Subnets {
// Note the docker API really wants the full CIDR subnet not just a single ip.
// https://github.com/containers/podman/pull/12328
if netutil.IsIPv4(subnet.IPNet.IP) {
ipv4Address = subnet.IPNet.String()
} else {
ipv6Address = subnet.IPNet.String()
}
}
macAddr = dev.MacAddress.String()
break
}
containerEndpoint := types.EndpointResource{
Name: con.Name(),
EndpointID: netData.EndpointID,
MacAddress: netData.MacAddress,
Name: st.name,
MacAddress: macAddr,
IPv4Address: ipv4Address,
IPv6Address: ipv6Address,
}
containerEndpoints[con.ID()] = containerEndpoint
containerEndpoints[st.id] = containerEndpoint
}
}
ipamConfigs := make([]dockerNetwork.IPAMConfig, 0, len(network.Subnets))
Expand Down Expand Up @@ -144,7 +171,7 @@ func convertLibpodNetworktoDockerNetwork(runtime *libpod.Runtime, network *netty
Peers: nil,
Services: nil,
}
return &report, nil
return &report
}

func ListNetworks(w http.ResponseWriter, r *http.Request) {
Expand All @@ -165,13 +192,14 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}
statuses, err := getContainerNetStatuses(runtime)
if err != nil {
utils.InternalServerError(w, err)
return
}
reports := make([]*types.NetworkResource, 0, len(nets))
for _, net := range nets {
report, err := convertLibpodNetworktoDockerNetwork(runtime, &net, true)
if err != nil {
utils.InternalServerError(w, err)
return
}
report := convertLibpodNetworktoDockerNetwork(runtime, statuses, &net, true)
reports = append(reports, report)
}
utils.WriteResponse(w, http.StatusOK, reports)
Expand Down

0 comments on commit c5be3ae

Please sign in to comment.