...

Source file src/github.com/Microsoft/hcsshim/hcn/hcnroute.go

Documentation: github.com/Microsoft/hcsshim/hcn

     1  //go:build windows
     2  
     3  package hcn
     4  
     5  import (
     6  	"encoding/json"
     7  	"errors"
     8  
     9  	"github.com/Microsoft/go-winio/pkg/guid"
    10  	"github.com/Microsoft/hcsshim/internal/interop"
    11  	"github.com/sirupsen/logrus"
    12  )
    13  
    14  // HostComputeRoute represents SDN routes.
    15  type HostComputeRoute struct {
    16  	ID                   string                  `json:"ID,omitempty"`
    17  	HostComputeEndpoints []string                `json:",omitempty"`
    18  	Setting              []SDNRoutePolicySetting `json:",omitempty"`
    19  	SchemaVersion        SchemaVersion           `json:",omitempty"`
    20  }
    21  
    22  // ListRoutes makes a call to list all available routes.
    23  func ListRoutes() ([]HostComputeRoute, error) {
    24  	hcnQuery := defaultQuery()
    25  	routes, err := ListRoutesQuery(hcnQuery)
    26  	if err != nil {
    27  		return nil, err
    28  	}
    29  	return routes, nil
    30  }
    31  
    32  // ListRoutesQuery makes a call to query the list of available routes.
    33  func ListRoutesQuery(query HostComputeQuery) ([]HostComputeRoute, error) {
    34  	queryJSON, err := json.Marshal(query)
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  
    39  	routes, err := enumerateRoutes(string(queryJSON))
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	return routes, nil
    44  }
    45  
    46  // GetRouteByID returns the route specified by Id.
    47  func GetRouteByID(routeID string) (*HostComputeRoute, error) {
    48  	hcnQuery := defaultQuery()
    49  	mapA := map[string]string{"ID": routeID}
    50  	filter, err := json.Marshal(mapA)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  	hcnQuery.Filter = string(filter)
    55  
    56  	routes, err := ListRoutesQuery(hcnQuery)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  	if len(routes) == 0 {
    61  		return nil, RouteNotFoundError{RouteId: routeID}
    62  	}
    63  	return &routes[0], err
    64  }
    65  
    66  // Create Route.
    67  func (route *HostComputeRoute) Create() (*HostComputeRoute, error) {
    68  	logrus.Debugf("hcn::HostComputeRoute::Create id=%s", route.ID)
    69  
    70  	jsonString, err := json.Marshal(route)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  
    75  	logrus.Debugf("hcn::HostComputeRoute::Create JSON: %s", jsonString)
    76  	route, hcnErr := createRoute(string(jsonString))
    77  	if hcnErr != nil {
    78  		return nil, hcnErr
    79  	}
    80  	return route, nil
    81  }
    82  
    83  // Delete Route.
    84  func (route *HostComputeRoute) Delete() error {
    85  	logrus.Debugf("hcn::HostComputeRoute::Delete id=%s", route.ID)
    86  
    87  	existingRoute, _ := GetRouteByID(route.ID)
    88  
    89  	if existingRoute != nil {
    90  		if err := deleteRoute(route.ID); err != nil {
    91  			return err
    92  		}
    93  	}
    94  
    95  	return nil
    96  }
    97  
    98  // AddEndpoint add an endpoint to a route
    99  // Since HCNRoute doesn't implement modify functionality, add operation is essentially delete and add
   100  func (route *HostComputeRoute) AddEndpoint(endpoint *HostComputeEndpoint) (*HostComputeRoute, error) {
   101  	logrus.Debugf("hcn::HostComputeRoute::AddEndpoint route=%s endpoint=%s", route.ID, endpoint.Id)
   102  
   103  	err := route.Delete()
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  
   108  	// Add Endpoint to the Existing List
   109  	route.HostComputeEndpoints = append(route.HostComputeEndpoints, endpoint.Id)
   110  
   111  	return route.Create()
   112  }
   113  
   114  // RemoveEndpoint removes an endpoint from a route
   115  // Since HCNRoute doesn't implement modify functionality, remove operation is essentially delete and add
   116  func (route *HostComputeRoute) RemoveEndpoint(endpoint *HostComputeEndpoint) (*HostComputeRoute, error) {
   117  	logrus.Debugf("hcn::HostComputeRoute::RemoveEndpoint route=%s endpoint=%s", route.ID, endpoint.Id)
   118  
   119  	err := route.Delete()
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  
   124  	// Create a list of all the endpoints besides the one being removed
   125  	i := 0
   126  	for index, endpointReference := range route.HostComputeEndpoints {
   127  		if endpointReference == endpoint.Id {
   128  			i = index
   129  			break
   130  		}
   131  	}
   132  
   133  	route.HostComputeEndpoints = append(route.HostComputeEndpoints[0:i], route.HostComputeEndpoints[i+1:]...)
   134  	return route.Create()
   135  }
   136  
   137  // AddRoute for the specified endpoints and SDN Route setting
   138  func AddRoute(endpoints []HostComputeEndpoint, destinationPrefix string, nextHop string, needEncapsulation bool) (*HostComputeRoute, error) {
   139  	logrus.Debugf("hcn::HostComputeRoute::AddRoute endpointId=%v, destinationPrefix=%v, nextHop=%v, needEncapsulation=%v", endpoints, destinationPrefix, nextHop, needEncapsulation)
   140  
   141  	if len(endpoints) <= 0 {
   142  		return nil, errors.New("missing endpoints")
   143  	}
   144  
   145  	route := &HostComputeRoute{
   146  		SchemaVersion: V2SchemaVersion(),
   147  		Setting: []SDNRoutePolicySetting{
   148  			{
   149  				DestinationPrefix: destinationPrefix,
   150  				NextHop:           nextHop,
   151  				NeedEncap:         needEncapsulation,
   152  			},
   153  		},
   154  	}
   155  
   156  	for _, endpoint := range endpoints {
   157  		route.HostComputeEndpoints = append(route.HostComputeEndpoints, endpoint.Id)
   158  	}
   159  
   160  	return route.Create()
   161  }
   162  
   163  func enumerateRoutes(query string) ([]HostComputeRoute, error) {
   164  	// Enumerate all routes Guids
   165  	var (
   166  		resultBuffer *uint16
   167  		routeBuffer  *uint16
   168  	)
   169  	hr := hcnEnumerateRoutes(query, &routeBuffer, &resultBuffer)
   170  	if err := checkForErrors("hcnEnumerateRoutes", hr, resultBuffer); err != nil {
   171  		return nil, err
   172  	}
   173  
   174  	routes := interop.ConvertAndFreeCoTaskMemString(routeBuffer)
   175  	var routeIds []guid.GUID
   176  	if err := json.Unmarshal([]byte(routes), &routeIds); err != nil {
   177  		return nil, err
   178  	}
   179  
   180  	var outputRoutes []HostComputeRoute
   181  	for _, routeGUID := range routeIds {
   182  		route, err := getRoute(routeGUID, query)
   183  		if err != nil {
   184  			return nil, err
   185  		}
   186  		outputRoutes = append(outputRoutes, *route)
   187  	}
   188  	return outputRoutes, nil
   189  }
   190  
   191  func getRoute(routeGUID guid.GUID, query string) (*HostComputeRoute, error) {
   192  	// Open routes.
   193  	var (
   194  		routeHandle      hcnRoute
   195  		resultBuffer     *uint16
   196  		propertiesBuffer *uint16
   197  	)
   198  	hr := hcnOpenRoute(&routeGUID, &routeHandle, &resultBuffer)
   199  	if err := checkForErrors("hcnOpenRoute", hr, resultBuffer); err != nil {
   200  		return nil, err
   201  	}
   202  	// Query routes.
   203  	hr = hcnQueryRouteProperties(routeHandle, query, &propertiesBuffer, &resultBuffer)
   204  	if err := checkForErrors("hcnQueryRouteProperties", hr, resultBuffer); err != nil {
   205  		return nil, err
   206  	}
   207  	properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
   208  	// Close routes.
   209  	hr = hcnCloseRoute(routeHandle)
   210  	if err := checkForErrors("hcnCloseRoute", hr, nil); err != nil {
   211  		return nil, err
   212  	}
   213  	// Convert output to HostComputeRoute
   214  	var outputRoute HostComputeRoute
   215  	if err := json.Unmarshal([]byte(properties), &outputRoute); err != nil {
   216  		return nil, err
   217  	}
   218  	return &outputRoute, nil
   219  }
   220  
   221  func createRoute(settings string) (*HostComputeRoute, error) {
   222  	// Create new route.
   223  	var (
   224  		routeHandle      hcnRoute
   225  		resultBuffer     *uint16
   226  		propertiesBuffer *uint16
   227  	)
   228  	routeGUID := guid.GUID{}
   229  	hr := hcnCreateRoute(&routeGUID, settings, &routeHandle, &resultBuffer)
   230  	if err := checkForErrors("hcnCreateRoute", hr, resultBuffer); err != nil {
   231  		return nil, err
   232  	}
   233  	// Query route.
   234  	hcnQuery := defaultQuery()
   235  	query, err := json.Marshal(hcnQuery)
   236  	if err != nil {
   237  		return nil, err
   238  	}
   239  	hr = hcnQueryRouteProperties(routeHandle, string(query), &propertiesBuffer, &resultBuffer)
   240  	if err := checkForErrors("hcnQueryRouteProperties", hr, resultBuffer); err != nil {
   241  		return nil, err
   242  	}
   243  	properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
   244  	// Close Route.
   245  	hr = hcnCloseRoute(routeHandle)
   246  	if err := checkForErrors("hcnCloseRoute", hr, nil); err != nil {
   247  		return nil, err
   248  	}
   249  	// Convert output to HostComputeRoute
   250  	var outputRoute HostComputeRoute
   251  	if err := json.Unmarshal([]byte(properties), &outputRoute); err != nil {
   252  		return nil, err
   253  	}
   254  	return &outputRoute, nil
   255  }
   256  
   257  func deleteRoute(routeID string) error {
   258  	routeGUID, err := guid.FromString(routeID)
   259  	if err != nil {
   260  		return errInvalidRouteID
   261  	}
   262  	var resultBuffer *uint16
   263  	hr := hcnDeleteRoute(&routeGUID, &resultBuffer)
   264  	if err := checkForErrors("hcnDeleteRoute", hr, resultBuffer); err != nil {
   265  		return err
   266  	}
   267  	return nil
   268  }
   269  

View as plain text