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