123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- //go:build windows
- package hcn
- import (
- "encoding/json"
- "errors"
- "github.com/Microsoft/go-winio/pkg/guid"
- "github.com/Microsoft/hcsshim/internal/interop"
- "github.com/sirupsen/logrus"
- )
- // HostComputeRoute represents SDN routes.
- type HostComputeRoute struct {
- ID string `json:"ID,omitempty"`
- HostComputeEndpoints []string `json:",omitempty"`
- Setting []SDNRoutePolicySetting `json:",omitempty"`
- SchemaVersion SchemaVersion `json:",omitempty"`
- }
- // ListRoutes makes a call to list all available routes.
- func ListRoutes() ([]HostComputeRoute, error) {
- hcnQuery := defaultQuery()
- routes, err := ListRoutesQuery(hcnQuery)
- if err != nil {
- return nil, err
- }
- return routes, nil
- }
- // ListRoutesQuery makes a call to query the list of available routes.
- func ListRoutesQuery(query HostComputeQuery) ([]HostComputeRoute, error) {
- queryJSON, err := json.Marshal(query)
- if err != nil {
- return nil, err
- }
- routes, err := enumerateRoutes(string(queryJSON))
- if err != nil {
- return nil, err
- }
- return routes, nil
- }
- // GetRouteByID returns the route specified by Id.
- func GetRouteByID(routeID string) (*HostComputeRoute, error) {
- hcnQuery := defaultQuery()
- mapA := map[string]string{"ID": routeID}
- filter, err := json.Marshal(mapA)
- if err != nil {
- return nil, err
- }
- hcnQuery.Filter = string(filter)
- routes, err := ListRoutesQuery(hcnQuery)
- if err != nil {
- return nil, err
- }
- if len(routes) == 0 {
- return nil, RouteNotFoundError{RouteId: routeID}
- }
- return &routes[0], err
- }
- // Create Route.
- func (route *HostComputeRoute) Create() (*HostComputeRoute, error) {
- logrus.Debugf("hcn::HostComputeRoute::Create id=%s", route.ID)
- jsonString, err := json.Marshal(route)
- if err != nil {
- return nil, err
- }
- logrus.Debugf("hcn::HostComputeRoute::Create JSON: %s", jsonString)
- route, hcnErr := createRoute(string(jsonString))
- if hcnErr != nil {
- return nil, hcnErr
- }
- return route, nil
- }
- // Delete Route.
- func (route *HostComputeRoute) Delete() error {
- logrus.Debugf("hcn::HostComputeRoute::Delete id=%s", route.ID)
- existingRoute, _ := GetRouteByID(route.ID)
- if existingRoute != nil {
- if err := deleteRoute(route.ID); err != nil {
- return err
- }
- }
- return nil
- }
- // AddEndpoint add an endpoint to a route
- // Since HCNRoute doesn't implement modify functionality, add operation is essentially delete and add
- func (route *HostComputeRoute) AddEndpoint(endpoint *HostComputeEndpoint) (*HostComputeRoute, error) {
- logrus.Debugf("hcn::HostComputeRoute::AddEndpoint route=%s endpoint=%s", route.ID, endpoint.Id)
- err := route.Delete()
- if err != nil {
- return nil, err
- }
- // Add Endpoint to the Existing List
- route.HostComputeEndpoints = append(route.HostComputeEndpoints, endpoint.Id)
- return route.Create()
- }
- // RemoveEndpoint removes an endpoint from a route
- // Since HCNRoute doesn't implement modify functionality, remove operation is essentially delete and add
- func (route *HostComputeRoute) RemoveEndpoint(endpoint *HostComputeEndpoint) (*HostComputeRoute, error) {
- logrus.Debugf("hcn::HostComputeRoute::RemoveEndpoint route=%s endpoint=%s", route.ID, endpoint.Id)
- err := route.Delete()
- if err != nil {
- return nil, err
- }
- // Create a list of all the endpoints besides the one being removed
- i := 0
- for index, endpointReference := range route.HostComputeEndpoints {
- if endpointReference == endpoint.Id {
- i = index
- break
- }
- }
- route.HostComputeEndpoints = append(route.HostComputeEndpoints[0:i], route.HostComputeEndpoints[i+1:]...)
- return route.Create()
- }
- // AddRoute for the specified endpoints and SDN Route setting
- func AddRoute(endpoints []HostComputeEndpoint, destinationPrefix string, nextHop string, needEncapsulation bool) (*HostComputeRoute, error) {
- logrus.Debugf("hcn::HostComputeRoute::AddRoute endpointId=%v, destinationPrefix=%v, nextHop=%v, needEncapsulation=%v", endpoints, destinationPrefix, nextHop, needEncapsulation)
- if len(endpoints) <= 0 {
- return nil, errors.New("missing endpoints")
- }
- route := &HostComputeRoute{
- SchemaVersion: V2SchemaVersion(),
- Setting: []SDNRoutePolicySetting{
- {
- DestinationPrefix: destinationPrefix,
- NextHop: nextHop,
- NeedEncap: needEncapsulation,
- },
- },
- }
- for _, endpoint := range endpoints {
- route.HostComputeEndpoints = append(route.HostComputeEndpoints, endpoint.Id)
- }
- return route.Create()
- }
- func enumerateRoutes(query string) ([]HostComputeRoute, error) {
- // Enumerate all routes Guids
- var (
- resultBuffer *uint16
- routeBuffer *uint16
- )
- hr := hcnEnumerateRoutes(query, &routeBuffer, &resultBuffer)
- if err := checkForErrors("hcnEnumerateRoutes", hr, resultBuffer); err != nil {
- return nil, err
- }
- routes := interop.ConvertAndFreeCoTaskMemString(routeBuffer)
- var routeIds []guid.GUID
- if err := json.Unmarshal([]byte(routes), &routeIds); err != nil {
- return nil, err
- }
- var outputRoutes []HostComputeRoute
- for _, routeGUID := range routeIds {
- route, err := getRoute(routeGUID, query)
- if err != nil {
- return nil, err
- }
- outputRoutes = append(outputRoutes, *route)
- }
- return outputRoutes, nil
- }
- func getRoute(routeGUID guid.GUID, query string) (*HostComputeRoute, error) {
- // Open routes.
- var (
- routeHandle hcnRoute
- resultBuffer *uint16
- propertiesBuffer *uint16
- )
- hr := hcnOpenRoute(&routeGUID, &routeHandle, &resultBuffer)
- if err := checkForErrors("hcnOpenRoute", hr, resultBuffer); err != nil {
- return nil, err
- }
- // Query routes.
- hr = hcnQueryRouteProperties(routeHandle, query, &propertiesBuffer, &resultBuffer)
- if err := checkForErrors("hcnQueryRouteProperties", hr, resultBuffer); err != nil {
- return nil, err
- }
- properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
- // Close routes.
- hr = hcnCloseRoute(routeHandle)
- if err := checkForErrors("hcnCloseRoute", hr, nil); err != nil {
- return nil, err
- }
- // Convert output to HostComputeRoute
- var outputRoute HostComputeRoute
- if err := json.Unmarshal([]byte(properties), &outputRoute); err != nil {
- return nil, err
- }
- return &outputRoute, nil
- }
- func createRoute(settings string) (*HostComputeRoute, error) {
- // Create new route.
- var (
- routeHandle hcnRoute
- resultBuffer *uint16
- propertiesBuffer *uint16
- )
- routeGUID := guid.GUID{}
- hr := hcnCreateRoute(&routeGUID, settings, &routeHandle, &resultBuffer)
- if err := checkForErrors("hcnCreateRoute", hr, resultBuffer); err != nil {
- return nil, err
- }
- // Query route.
- hcnQuery := defaultQuery()
- query, err := json.Marshal(hcnQuery)
- if err != nil {
- return nil, err
- }
- hr = hcnQueryRouteProperties(routeHandle, string(query), &propertiesBuffer, &resultBuffer)
- if err := checkForErrors("hcnQueryRouteProperties", hr, resultBuffer); err != nil {
- return nil, err
- }
- properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
- // Close Route.
- hr = hcnCloseRoute(routeHandle)
- if err := checkForErrors("hcnCloseRoute", hr, nil); err != nil {
- return nil, err
- }
- // Convert output to HostComputeRoute
- var outputRoute HostComputeRoute
- if err := json.Unmarshal([]byte(properties), &outputRoute); err != nil {
- return nil, err
- }
- return &outputRoute, nil
- }
- func deleteRoute(routeID string) error {
- routeGUID, err := guid.FromString(routeID)
- if err != nil {
- return errInvalidRouteID
- }
- var resultBuffer *uint16
- hr := hcnDeleteRoute(&routeGUID, &resultBuffer)
- if err := checkForErrors("hcnDeleteRoute", hr, resultBuffer); err != nil {
- return err
- }
- return nil
- }
|