hnsendpoint.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. //go:build windows
  2. package hns
  3. import (
  4. "encoding/json"
  5. "net"
  6. "strings"
  7. "github.com/sirupsen/logrus"
  8. )
  9. // HNSEndpoint represents a network endpoint in HNS
  10. type HNSEndpoint struct {
  11. Id string `json:"ID,omitempty"`
  12. Name string `json:",omitempty"`
  13. VirtualNetwork string `json:",omitempty"`
  14. VirtualNetworkName string `json:",omitempty"`
  15. Policies []json.RawMessage `json:",omitempty"`
  16. MacAddress string `json:",omitempty"`
  17. IPAddress net.IP `json:",omitempty"`
  18. IPv6Address net.IP `json:",omitempty"`
  19. DNSSuffix string `json:",omitempty"`
  20. DNSServerList string `json:",omitempty"`
  21. DNSDomain string `json:",omitempty"`
  22. GatewayAddress string `json:",omitempty"`
  23. GatewayAddressV6 string `json:",omitempty"`
  24. EnableInternalDNS bool `json:",omitempty"`
  25. DisableICC bool `json:",omitempty"`
  26. PrefixLength uint8 `json:",omitempty"`
  27. IPv6PrefixLength uint8 `json:",omitempty"`
  28. IsRemoteEndpoint bool `json:",omitempty"`
  29. EnableLowMetric bool `json:",omitempty"`
  30. Namespace *Namespace `json:",omitempty"`
  31. EncapOverhead uint16 `json:",omitempty"`
  32. SharedContainers []string `json:",omitempty"`
  33. }
  34. // SystemType represents the type of the system on which actions are done
  35. type SystemType string
  36. // SystemType const
  37. const (
  38. ContainerType SystemType = "Container"
  39. VirtualMachineType SystemType = "VirtualMachine"
  40. HostType SystemType = "Host"
  41. )
  42. // EndpointAttachDetachRequest is the structure used to send request to the container to modify the system
  43. // Supported resource types are Network and Request Types are Add/Remove
  44. type EndpointAttachDetachRequest struct {
  45. ContainerID string `json:"ContainerId,omitempty"`
  46. SystemType SystemType `json:"SystemType"`
  47. CompartmentID uint16 `json:"CompartmentId,omitempty"`
  48. VirtualNICName string `json:"VirtualNicName,omitempty"`
  49. }
  50. // EndpointResquestResponse is object to get the endpoint request response
  51. type EndpointResquestResponse struct {
  52. Success bool
  53. Error string
  54. }
  55. // EndpointStats is the object that has stats for a given endpoint
  56. type EndpointStats struct {
  57. BytesReceived uint64 `json:"BytesReceived"`
  58. BytesSent uint64 `json:"BytesSent"`
  59. DroppedPacketsIncoming uint64 `json:"DroppedPacketsIncoming"`
  60. DroppedPacketsOutgoing uint64 `json:"DroppedPacketsOutgoing"`
  61. EndpointID string `json:"EndpointId"`
  62. InstanceID string `json:"InstanceId"`
  63. PacketsReceived uint64 `json:"PacketsReceived"`
  64. PacketsSent uint64 `json:"PacketsSent"`
  65. }
  66. // HNSEndpointRequest makes a HNS call to modify/query a network endpoint
  67. func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) {
  68. endpoint := &HNSEndpoint{}
  69. err := hnsCall(method, "/endpoints/"+path, request, &endpoint)
  70. if err != nil {
  71. return nil, err
  72. }
  73. return endpoint, nil
  74. }
  75. // HNSListEndpointRequest makes a HNS call to query the list of available endpoints
  76. func HNSListEndpointRequest() ([]HNSEndpoint, error) {
  77. var endpoint []HNSEndpoint
  78. err := hnsCall("GET", "/endpoints/", "", &endpoint)
  79. if err != nil {
  80. return nil, err
  81. }
  82. return endpoint, nil
  83. }
  84. // hnsEndpointStatsRequest makes a HNS call to query the stats for a given endpoint ID
  85. func hnsEndpointStatsRequest(id string) (*EndpointStats, error) {
  86. var stats EndpointStats
  87. err := hnsCall("GET", "/endpointstats/"+id, "", &stats)
  88. if err != nil {
  89. return nil, err
  90. }
  91. return &stats, nil
  92. }
  93. // GetHNSEndpointByID get the Endpoint by ID
  94. func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) {
  95. return HNSEndpointRequest("GET", endpointID, "")
  96. }
  97. // GetHNSEndpointStats get the stats for a n Endpoint by ID
  98. func GetHNSEndpointStats(endpointID string) (*EndpointStats, error) {
  99. return hnsEndpointStatsRequest(endpointID)
  100. }
  101. // GetHNSEndpointByName gets the endpoint filtered by Name
  102. func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) {
  103. hnsResponse, err := HNSListEndpointRequest()
  104. if err != nil {
  105. return nil, err
  106. }
  107. for _, hnsEndpoint := range hnsResponse {
  108. if hnsEndpoint.Name == endpointName {
  109. return &hnsEndpoint, nil
  110. }
  111. }
  112. return nil, EndpointNotFoundError{EndpointName: endpointName}
  113. }
  114. type endpointAttachInfo struct {
  115. SharedContainers json.RawMessage `json:",omitempty"`
  116. }
  117. func (endpoint *HNSEndpoint) IsAttached(vID string) (bool, error) {
  118. attachInfo := endpointAttachInfo{}
  119. err := hnsCall("GET", "/endpoints/"+endpoint.Id, "", &attachInfo)
  120. // Return false allows us to just return the err
  121. if err != nil {
  122. return false, err
  123. }
  124. if strings.Contains(strings.ToLower(string(attachInfo.SharedContainers)), strings.ToLower(vID)) {
  125. return true, nil
  126. }
  127. return false, nil
  128. }
  129. // Create Endpoint by sending EndpointRequest to HNS. TODO: Create a separate HNS interface to place all these methods
  130. func (endpoint *HNSEndpoint) Create() (*HNSEndpoint, error) {
  131. operation := "Create"
  132. title := "hcsshim::HNSEndpoint::" + operation
  133. logrus.Debugf(title+" id=%s", endpoint.Id)
  134. jsonString, err := json.Marshal(endpoint)
  135. if err != nil {
  136. return nil, err
  137. }
  138. return HNSEndpointRequest("POST", "", string(jsonString))
  139. }
  140. // Delete Endpoint by sending EndpointRequest to HNS
  141. func (endpoint *HNSEndpoint) Delete() (*HNSEndpoint, error) {
  142. operation := "Delete"
  143. title := "hcsshim::HNSEndpoint::" + operation
  144. logrus.Debugf(title+" id=%s", endpoint.Id)
  145. return HNSEndpointRequest("DELETE", endpoint.Id, "")
  146. }
  147. // Update Endpoint
  148. func (endpoint *HNSEndpoint) Update() (*HNSEndpoint, error) {
  149. operation := "Update"
  150. title := "hcsshim::HNSEndpoint::" + operation
  151. logrus.Debugf(title+" id=%s", endpoint.Id)
  152. jsonString, err := json.Marshal(endpoint)
  153. if err != nil {
  154. return nil, err
  155. }
  156. err = hnsCall("POST", "/endpoints/"+endpoint.Id, string(jsonString), &endpoint)
  157. return endpoint, err
  158. }
  159. // ApplyACLPolicy applies a set of ACL Policies on the Endpoint
  160. func (endpoint *HNSEndpoint) ApplyACLPolicy(policies ...*ACLPolicy) error {
  161. operation := "ApplyACLPolicy"
  162. title := "hcsshim::HNSEndpoint::" + operation
  163. logrus.Debugf(title+" id=%s", endpoint.Id)
  164. for _, policy := range policies {
  165. if policy == nil {
  166. continue
  167. }
  168. jsonString, err := json.Marshal(policy)
  169. if err != nil {
  170. return err
  171. }
  172. endpoint.Policies = append(endpoint.Policies, jsonString)
  173. }
  174. _, err := endpoint.Update()
  175. return err
  176. }
  177. // ApplyProxyPolicy applies a set of Proxy Policies on the Endpoint
  178. func (endpoint *HNSEndpoint) ApplyProxyPolicy(policies ...*ProxyPolicy) error {
  179. operation := "ApplyProxyPolicy"
  180. title := "hcsshim::HNSEndpoint::" + operation
  181. logrus.Debugf(title+" id=%s", endpoint.Id)
  182. for _, policy := range policies {
  183. if policy == nil {
  184. continue
  185. }
  186. jsonString, err := json.Marshal(policy)
  187. if err != nil {
  188. return err
  189. }
  190. endpoint.Policies = append(endpoint.Policies, jsonString)
  191. }
  192. _, err := endpoint.Update()
  193. return err
  194. }
  195. // ContainerAttach attaches an endpoint to container
  196. func (endpoint *HNSEndpoint) ContainerAttach(containerID string, compartmentID uint16) error {
  197. operation := "ContainerAttach"
  198. title := "hcsshim::HNSEndpoint::" + operation
  199. logrus.Debugf(title+" id=%s", endpoint.Id)
  200. requestMessage := &EndpointAttachDetachRequest{
  201. ContainerID: containerID,
  202. CompartmentID: compartmentID,
  203. SystemType: ContainerType,
  204. }
  205. response := &EndpointResquestResponse{}
  206. jsonString, err := json.Marshal(requestMessage)
  207. if err != nil {
  208. return err
  209. }
  210. return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
  211. }
  212. // ContainerDetach detaches an endpoint from container
  213. func (endpoint *HNSEndpoint) ContainerDetach(containerID string) error {
  214. operation := "ContainerDetach"
  215. title := "hcsshim::HNSEndpoint::" + operation
  216. logrus.Debugf(title+" id=%s", endpoint.Id)
  217. requestMessage := &EndpointAttachDetachRequest{
  218. ContainerID: containerID,
  219. SystemType: ContainerType,
  220. }
  221. response := &EndpointResquestResponse{}
  222. jsonString, err := json.Marshal(requestMessage)
  223. if err != nil {
  224. return err
  225. }
  226. return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
  227. }
  228. // HostAttach attaches a nic on the host
  229. func (endpoint *HNSEndpoint) HostAttach(compartmentID uint16) error {
  230. operation := "HostAttach"
  231. title := "hcsshim::HNSEndpoint::" + operation
  232. logrus.Debugf(title+" id=%s", endpoint.Id)
  233. requestMessage := &EndpointAttachDetachRequest{
  234. CompartmentID: compartmentID,
  235. SystemType: HostType,
  236. }
  237. response := &EndpointResquestResponse{}
  238. jsonString, err := json.Marshal(requestMessage)
  239. if err != nil {
  240. return err
  241. }
  242. return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
  243. }
  244. // HostDetach detaches a nic on the host
  245. func (endpoint *HNSEndpoint) HostDetach() error {
  246. operation := "HostDetach"
  247. title := "hcsshim::HNSEndpoint::" + operation
  248. logrus.Debugf(title+" id=%s", endpoint.Id)
  249. requestMessage := &EndpointAttachDetachRequest{
  250. SystemType: HostType,
  251. }
  252. response := &EndpointResquestResponse{}
  253. jsonString, err := json.Marshal(requestMessage)
  254. if err != nil {
  255. return err
  256. }
  257. return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
  258. }
  259. // VirtualMachineNICAttach attaches a endpoint to a virtual machine
  260. func (endpoint *HNSEndpoint) VirtualMachineNICAttach(virtualMachineNICName string) error {
  261. operation := "VirtualMachineNicAttach"
  262. title := "hcsshim::HNSEndpoint::" + operation
  263. logrus.Debugf(title+" id=%s", endpoint.Id)
  264. requestMessage := &EndpointAttachDetachRequest{
  265. VirtualNICName: virtualMachineNICName,
  266. SystemType: VirtualMachineType,
  267. }
  268. response := &EndpointResquestResponse{}
  269. jsonString, err := json.Marshal(requestMessage)
  270. if err != nil {
  271. return err
  272. }
  273. return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response)
  274. }
  275. // VirtualMachineNICDetach detaches a endpoint from a virtual machine
  276. func (endpoint *HNSEndpoint) VirtualMachineNICDetach() error {
  277. operation := "VirtualMachineNicDetach"
  278. title := "hcsshim::HNSEndpoint::" + operation
  279. logrus.Debugf(title+" id=%s", endpoint.Id)
  280. requestMessage := &EndpointAttachDetachRequest{
  281. SystemType: VirtualMachineType,
  282. }
  283. response := &EndpointResquestResponse{}
  284. jsonString, err := json.Marshal(requestMessage)
  285. if err != nil {
  286. return err
  287. }
  288. return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response)
  289. }