You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: network.go
    path of file: ./repos/docker-ce/components/engine/vendor/github.com/docker/swarmkit/manager/allocator
    
    the code of the file until where you have to start completion: package allocator

import (
	"context"
	"fmt"
	"time"

	"github.com/docker/go-events"
	"github.com/docker/swarmk
    
func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
	var netConfig *cnmallocator.NetworkConfig
	// There are two ways user can invoke swarm init
	// with default address pool & vxlan port  or with only vxlan port
	// hence we need two different way to construct netconfig
	if a.networkConfig != nil {
		if a.networkConfig.DefaultAddrPool != nil {
			netConfig = &cnmallocator.NetworkConfig{
				DefaultAddrPool: a.networkConfig.DefaultAddrPool,
				SubnetSize:      a.networkConfig.SubnetSize,
				VXLANUDPPort:    a.networkConfig.VXLANUDPPort,
			}
		} else if a.networkConfig.VXLANUDPPort != 0 {
			netConfig = &cnmallocator.NetworkConfig{
				DefaultAddrPool: nil,
				SubnetSize:      0,
				VXLANUDPPort:    a.networkConfig.VXLANUDPPort,
			}
		}
	}

	na, err := cnmallocator.New(a.pluginGetter, netConfig)
	if err != nil {
		return err
	}

	nc := &networkContext{
		nwkAllocator:        na,
		pendingTasks:        make(map[string]*api.Task),
		unallocatedTasks:    make(map[string]*api.Task),
		unallocatedServices: make(map[string]*api.Service),
		unallocatedNetworks: make(map[string]*api.Network),
		lastRetry:           time.Now(),
	}
	a.netCtx = nc
	defer func() {
		// Clear a.netCtx if initialization was unsuccessful.
		if err != nil {
			a.netCtx = nil
		}
	}()

	// Ingress network is now created at cluster's first time creation.
	// Check if we have the ingress network. If found, make sure it is
	// allocated, before reading all network objects for allocation.
	// If not found, it means it was removed by user, nothing to do here.
	ingressNetwork, err := GetIngressNetwork(a.store)
	switch err {
	case nil:
		// Try to complete ingress network allocation before anything else so
		// that the we can get the preferred subnet for ingress network.
		nc.ingressNetwork = ingressNetwork
		if !na.IsAllocated(nc.ingressNetwork) {
			if err := a.allocateNetwork(ctx, nc.ingressNetwork); err != nil {
				log.G(ctx).WithError(err).Error("failed allocating ingress network during init")
			} else if err := a.store.Batch(func(batch *store.Batch) error {
				if err := a.commitAllocatedNetwork(ctx, batch, nc.ingressNetwork); err != nil {
					log.G(ctx).WithError(err).Error("failed committing allocation of ingress network during init")
				}
				return nil
			}); err != nil {
				log.G(ctx).WithError(err).Error("failed committing allocation of ingress network during init")
			}
		}
	case ErrNoIngress:
		// Ingress network is not present in store, It means user removed it
		// and did not create a new one.
	default:
		return errors.Wrap(err, "failure while looking for ingress network during init")
	}

	// First, allocate (read it as restore) objects likes network,nodes,serives
	// and tasks that were already allocated. Then go on the allocate objects
	// that are in raft and were previously not allocated. The reason being, during
	// restore, we  make sure that we populate the allocated states of
	// the objects in the raft onto our in memory state.
	if err := a.allocateNetworks(ctx, true); err != nil {
		return err
	}

	if err := a.allocateNodes(ctx, true); err != nil {
		return err
	}

	if err := a.allocateServices(ctx, true); err != nil {
		return err
	}
	if err := a.allocateTasks(ctx, true); err != nil {
		return err
	}
	// Now allocate objects that were not previously allocated
	// but were present in the raft.
	if err := a.allocateNetworks(ctx, false); err != nil {
		return err
	}

	if err := a.allocateNodes(ctx, false); err != nil {
		return err
	}

	if err := a.allocateServices(ctx, false); err != nil {
		return err
	}
	return a.allocateTasks(ctx, false)
}