hcnroute.go 7.4 KB

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