network/hnswrapper/hnsv2wrapperwithtimeout.go (318 lines of code) (raw):
//go:build windows
// +build windows
package hnswrapper
import (
"context"
"fmt"
"time"
"github.com/pkg/errors"
"github.com/Microsoft/hcsshim/hcn"
)
// ErrHNSCallTimeout - hns call timeout
var ErrHNSCallTimeout = errors.New("timed out calling hns")
type Hnsv2wrapperwithtimeout struct {
Hnsv2 HnsV2WrapperInterface
// hnsCallTimeout indicates the time to wait for hns calls before timing out
HnsCallTimeout time.Duration
}
type CreateEndpointFuncResult struct {
endpoint *hcn.HostComputeEndpoint
Err error
}
type GetEndpointByIDFuncResult struct {
endpoint *hcn.HostComputeEndpoint
Err error
}
type ListEndpointsFuncResult struct {
endpoints []hcn.HostComputeEndpoint
Err error
}
type CreateNetworkFuncResult struct {
network *hcn.HostComputeNetwork
Err error
}
type GetNamespaceByIDFuncResult struct {
namespace *hcn.HostComputeNamespace
Err error
}
type GetNetworkByNameFuncResult struct {
network *hcn.HostComputeNetwork
Err error
}
type GetNetworkByIDFuncResult struct {
network *hcn.HostComputeNetwork
Err error
}
func (h Hnsv2wrapperwithtimeout) CreateEndpoint(endpoint *hcn.HostComputeEndpoint) (*hcn.HostComputeEndpoint, error) {
r := make(chan CreateEndpointFuncResult)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
endpoint, err := h.Hnsv2.CreateEndpoint(endpoint)
r <- CreateEndpointFuncResult{
endpoint: endpoint,
Err: err,
}
}()
// Listen on our channel AND a timeout channel - which ever happens first.
select {
case res := <-r:
return res.endpoint, res.Err
case <-ctx.Done():
return nil, errors.Wrapf(ErrHNSCallTimeout, "CreateEndpoint timeout value is %v ", h.HnsCallTimeout.String())
}
}
func (h Hnsv2wrapperwithtimeout) DeleteEndpoint(endpoint *hcn.HostComputeEndpoint) error {
r := make(chan error)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
r <- h.Hnsv2.DeleteEndpoint(endpoint)
}()
// Listen on our channel AND a timeout channel - which ever happens first.
select {
case res := <-r:
return res
case <-ctx.Done():
return errors.Wrapf(ErrHNSCallTimeout, "DeleteEndpoint timeout value is %v ", h.HnsCallTimeout.String())
}
}
func (h Hnsv2wrapperwithtimeout) CreateNetwork(network *hcn.HostComputeNetwork) (*hcn.HostComputeNetwork, error) {
r := make(chan CreateNetworkFuncResult)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
network, err := h.Hnsv2.CreateNetwork(network)
r <- CreateNetworkFuncResult{
network: network,
Err: err,
}
}()
select {
case res := <-r:
return res.network, res.Err
case <-ctx.Done():
return nil, errors.Wrapf(ErrHNSCallTimeout, "CreateNetwork timeout value is %v ", h.HnsCallTimeout.String())
}
}
func (h Hnsv2wrapperwithtimeout) DeleteNetwork(network *hcn.HostComputeNetwork) error {
r := make(chan error)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
r <- h.Hnsv2.DeleteNetwork(network)
}()
// Listen on our channel AND a timeout channel - which ever happens first.
select {
case res := <-r:
return res
case <-ctx.Done():
return errors.Wrapf(ErrHNSCallTimeout, "DeleteNetwork timeout value is %v ", h.HnsCallTimeout.String())
}
}
func (h Hnsv2wrapperwithtimeout) ModifyNetworkSettings(network *hcn.HostComputeNetwork, request *hcn.ModifyNetworkSettingRequest) error {
r := make(chan error)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
r <- h.Hnsv2.ModifyNetworkSettings(network, request)
}()
// Listen on our channel AND a timeout channel - which ever happens first.
select {
case res := <-r:
return res
case <-ctx.Done():
return errors.Wrapf(ErrHNSCallTimeout, "ModifyNetworkSettings timeout value is %v ", h.HnsCallTimeout.String())
}
}
func (h Hnsv2wrapperwithtimeout) AddNetworkPolicy(network *hcn.HostComputeNetwork, networkPolicy hcn.PolicyNetworkRequest) error {
r := make(chan error)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
r <- h.Hnsv2.AddNetworkPolicy(network, networkPolicy)
}()
// Listen on our channel AND a timeout channel - which ever happens first.
select {
case res := <-r:
return res
case <-ctx.Done():
return errors.Wrapf(ErrHNSCallTimeout, "AddNetworkPolicy timeout value is %v ", h.HnsCallTimeout.String())
}
}
func (h Hnsv2wrapperwithtimeout) RemoveNetworkPolicy(network *hcn.HostComputeNetwork, networkPolicy hcn.PolicyNetworkRequest) error {
r := make(chan error)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
r <- h.Hnsv2.RemoveNetworkPolicy(network, networkPolicy)
}()
// Listen on our channel AND a timeout channel - which ever happens first.
select {
case res := <-r:
return res
case <-ctx.Done():
return errors.Wrapf(ErrHNSCallTimeout, "RemoveNetworkPolicy timeout value is %v ", h.HnsCallTimeout.String())
}
}
func (h Hnsv2wrapperwithtimeout) GetNamespaceByID(netNamespacePath string) (*hcn.HostComputeNamespace, error) {
r := make(chan GetNamespaceByIDFuncResult)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
namespace, err := h.Hnsv2.GetNamespaceByID(netNamespacePath)
r <- GetNamespaceByIDFuncResult{
namespace: namespace,
Err: err,
}
}()
// Listen on our channel AND a timeout channel - which ever happens first.
select {
case res := <-r:
return res.namespace, res.Err
case <-ctx.Done():
return nil, errors.Wrapf(ErrHNSCallTimeout, "GetNamespaceByID timeout value is %v ", h.HnsCallTimeout.String())
}
}
func (h Hnsv2wrapperwithtimeout) AddNamespaceEndpoint(namespaceId string, endpointId string) error {
r := make(chan error)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
r <- h.Hnsv2.AddNamespaceEndpoint(namespaceId, endpointId)
}()
// Listen on our channel AND a timeout channel - which ever happens first.
select {
case res := <-r:
return res
case <-ctx.Done():
return fmt.Errorf("AddNamespaceEndpoint %w , timeout value is %s seconds", ErrHNSCallTimeout, h.HnsCallTimeout.String())
}
}
func (h Hnsv2wrapperwithtimeout) RemoveNamespaceEndpoint(namespaceId string, endpointId string) error {
r := make(chan error)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
r <- h.Hnsv2.RemoveNamespaceEndpoint(namespaceId, endpointId)
}()
// Listen on our channel AND a timeout channel - which ever happens first.
select {
case res := <-r:
return res
case <-ctx.Done():
return errors.Wrapf(ErrHNSCallTimeout, "RemoveNamespaceEndpoint %w , timeout value is %s seconds", h.HnsCallTimeout.String())
}
}
func (h Hnsv2wrapperwithtimeout) GetNetworkByName(networkName string) (*hcn.HostComputeNetwork, error) {
r := make(chan GetNetworkByNameFuncResult)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
network, err := h.Hnsv2.GetNetworkByName(networkName)
r <- GetNetworkByNameFuncResult{
network: network,
Err: err,
}
}()
// Listen on our channel AND a timeout channel - which ever happens first.
select {
case res := <-r:
return res.network, res.Err
case <-ctx.Done():
return nil, errors.Wrapf(ErrHNSCallTimeout, "GetNetworkByName %w , timeout value is %s seconds", h.HnsCallTimeout.String())
}
}
func (h Hnsv2wrapperwithtimeout) GetNetworkByID(networkId string) (*hcn.HostComputeNetwork, error) {
r := make(chan GetNetworkByIDFuncResult)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
network, err := h.Hnsv2.GetNetworkByID(networkId)
r <- GetNetworkByIDFuncResult{
network: network,
Err: err,
}
}()
// Listen on our channel AND a timeout channel - which ever happens first.
select {
case res := <-r:
return res.network, res.Err
case <-ctx.Done():
return nil, errors.Wrapf(ErrHNSCallTimeout, "GetNetworkByID %w , timeout value is %s seconds", h.HnsCallTimeout.String())
}
}
func (h Hnsv2wrapperwithtimeout) GetEndpointByID(endpointId string) (*hcn.HostComputeEndpoint, error) {
r := make(chan GetEndpointByIDFuncResult)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
endpoint, err := h.Hnsv2.GetEndpointByID(endpointId)
r <- GetEndpointByIDFuncResult{
endpoint: endpoint,
Err: err,
}
}()
// Listen on our channel AND a timeout channel - which ever happens first.
select {
case res := <-r:
return res.endpoint, res.Err
case <-ctx.Done():
return nil, errors.Wrapf(ErrHNSCallTimeout, "GetEndpointByID %w , timeout value is %s seconds", h.HnsCallTimeout.String())
}
}
func (h Hnsv2wrapperwithtimeout) ListEndpointsOfNetwork(networkId string) ([]hcn.HostComputeEndpoint, error) {
r := make(chan ListEndpointsFuncResult)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
endpoints, err := h.Hnsv2.ListEndpointsOfNetwork(networkId)
r <- ListEndpointsFuncResult{
endpoints: endpoints,
Err: err,
}
}()
// Listen on our channel AND a timeout channel - which ever happens first.
select {
case res := <-r:
return res.endpoints, res.Err
case <-ctx.Done():
return nil, errors.Wrapf(ErrHNSCallTimeout, "ListEndpointsOfNetwork %w , timeout value is %s seconds", h.HnsCallTimeout.String())
}
}
// NOTE see assumptions of hnsv2wrapperfake.ListEndpointsQuery
func (h Hnsv2wrapperwithtimeout) ListEndpointsQuery(query hcn.HostComputeQuery) ([]hcn.HostComputeEndpoint, error) {
// must be a buffered chan of size 1, otherwise it leaks goroutines when trying to send to the channel after the timeout has fired
r := make(chan ListEndpointsFuncResult, 1)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
endpoints, err := h.Hnsv2.ListEndpointsQuery(query)
r <- ListEndpointsFuncResult{
endpoints: endpoints,
Err: err,
}
}()
// Listen on our channel AND a timeout channel - which ever happens first.
select {
case res := <-r:
return res.endpoints, res.Err
case <-ctx.Done():
return nil, errors.Wrapf(ErrHNSCallTimeout, "ListEndpointsOfNetwork, timeout value is %s seconds", h.HnsCallTimeout.String())
}
}
func (h Hnsv2wrapperwithtimeout) ApplyEndpointPolicy(endpoint *hcn.HostComputeEndpoint, requestType hcn.RequestType, endpointPolicy hcn.PolicyEndpointRequest) error {
r := make(chan error)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
r <- h.Hnsv2.ApplyEndpointPolicy(endpoint, requestType, endpointPolicy)
}()
// Listen on our channel AND a timeout channel - which ever happens first.
select {
case res := <-r:
return res
case <-ctx.Done():
return errors.Wrapf(ErrHNSCallTimeout, "ApplyEndpointPolicy %w , timeout value is %s seconds", h.HnsCallTimeout.String())
}
}
func (h Hnsv2wrapperwithtimeout) GetEndpointByName(endpointName string) (*hcn.HostComputeEndpoint, error) {
r := make(chan GetEndpointByIDFuncResult)
ctx, cancel := context.WithTimeout(context.TODO(), h.HnsCallTimeout)
defer cancel()
go func() {
endpoint, err := h.Hnsv2.GetEndpointByName(endpointName)
r <- GetEndpointByIDFuncResult{
endpoint: endpoint,
Err: err,
}
}()
// Listen on our channel AND a timeout channel - which ever happens first.
select {
case res := <-r:
return res.endpoint, res.Err
case <-ctx.Done():
return nil, errors.Wrapf(ErrHNSCallTimeout, "GetEndpointByName %w , timeout value is %s seconds", h.HnsCallTimeout.String())
}
}
func (h Hnsv2wrapperwithtimeout) HNSV2Supported() error {
return nil
}