1package hcsshim 2 3import ( 4 "encoding/json" 5 "fmt" 6 "net" 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 DNSSuffix string `json:",omitempty"` 21 DNSServerList string `json:",omitempty"` 22 GatewayAddress string `json:",omitempty"` 23 EnableInternalDNS bool `json:",omitempty"` 24 DisableICC bool `json:",omitempty"` 25 PrefixLength uint8 `json:",omitempty"` 26 IsRemoteEndpoint bool `json:",omitempty"` 27} 28 29//SystemType represents the type of the system on which actions are done 30type SystemType string 31 32// SystemType const 33const ( 34 ContainerType SystemType = "Container" 35 VirtualMachineType SystemType = "VirtualMachine" 36 HostType SystemType = "Host" 37) 38 39// EndpointAttachDetachRequest is the structure used to send request to the container to modify the system 40// Supported resource types are Network and Request Types are Add/Remove 41type EndpointAttachDetachRequest struct { 42 ContainerID string `json:"ContainerId,omitempty"` 43 SystemType SystemType `json:"SystemType"` 44 CompartmentID uint16 `json:"CompartmentId,omitempty"` 45 VirtualNICName string `json:"VirtualNicName,omitempty"` 46} 47 48// EndpointResquestResponse is object to get the endpoint request response 49type EndpointResquestResponse struct { 50 Success bool 51 Error string 52} 53 54// HNSEndpointRequest makes a HNS call to modify/query a network endpoint 55func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) { 56 endpoint := &HNSEndpoint{} 57 err := hnsCall(method, "/endpoints/"+path, request, &endpoint) 58 if err != nil { 59 return nil, err 60 } 61 62 return endpoint, nil 63} 64 65// HNSListEndpointRequest makes a HNS call to query the list of available endpoints 66func HNSListEndpointRequest() ([]HNSEndpoint, error) { 67 var endpoint []HNSEndpoint 68 err := hnsCall("GET", "/endpoints/", "", &endpoint) 69 if err != nil { 70 return nil, err 71 } 72 73 return endpoint, nil 74} 75 76// HotAttachEndpoint makes a HCS Call to attach the endpoint to the container 77func HotAttachEndpoint(containerID string, endpointID string) error { 78 return modifyNetworkEndpoint(containerID, endpointID, Add) 79} 80 81// HotDetachEndpoint makes a HCS Call to detach the endpoint from the container 82func HotDetachEndpoint(containerID string, endpointID string) error { 83 return modifyNetworkEndpoint(containerID, endpointID, Remove) 84} 85 86// ModifyContainer corresponding to the container id, by sending a request 87func modifyContainer(id string, request *ResourceModificationRequestResponse) error { 88 container, err := OpenContainer(id) 89 if err != nil { 90 if IsNotExist(err) { 91 return ErrComputeSystemDoesNotExist 92 } 93 return getInnerError(err) 94 } 95 defer container.Close() 96 err = container.Modify(request) 97 if err != nil { 98 if IsNotSupported(err) { 99 return ErrPlatformNotSupported 100 } 101 return getInnerError(err) 102 } 103 104 return nil 105} 106 107func modifyNetworkEndpoint(containerID string, endpointID string, request RequestType) error { 108 requestMessage := &ResourceModificationRequestResponse{ 109 Resource: Network, 110 Request: request, 111 Data: endpointID, 112 } 113 err := modifyContainer(containerID, requestMessage) 114 115 if err != nil { 116 return err 117 } 118 119 return nil 120} 121 122// GetHNSEndpointByID get the Endpoint by ID 123func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) { 124 return HNSEndpointRequest("GET", endpointID, "") 125} 126 127// GetHNSEndpointByName gets the endpoint filtered by Name 128func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) { 129 hnsResponse, err := HNSListEndpointRequest() 130 if err != nil { 131 return nil, err 132 } 133 for _, hnsEndpoint := range hnsResponse { 134 if hnsEndpoint.Name == endpointName { 135 return &hnsEndpoint, nil 136 } 137 } 138 return nil, fmt.Errorf("Endpoint %v not found", endpointName) 139} 140 141// Create Endpoint by sending EndpointRequest to HNS. TODO: Create a separate HNS interface to place all these methods 142func (endpoint *HNSEndpoint) Create() (*HNSEndpoint, error) { 143 operation := "Create" 144 title := "HCSShim::HNSEndpoint::" + operation 145 logrus.Debugf(title+" id=%s", endpoint.Id) 146 147 jsonString, err := json.Marshal(endpoint) 148 if err != nil { 149 return nil, err 150 } 151 return HNSEndpointRequest("POST", "", string(jsonString)) 152} 153 154// Delete Endpoint by sending EndpointRequest to HNS 155func (endpoint *HNSEndpoint) Delete() (*HNSEndpoint, error) { 156 operation := "Delete" 157 title := "HCSShim::HNSEndpoint::" + operation 158 logrus.Debugf(title+" id=%s", endpoint.Id) 159 160 return HNSEndpointRequest("DELETE", endpoint.Id, "") 161} 162 163// Update Endpoint 164func (endpoint *HNSEndpoint) Update() (*HNSEndpoint, error) { 165 operation := "Update" 166 title := "HCSShim::HNSEndpoint::" + operation 167 logrus.Debugf(title+" id=%s", endpoint.Id) 168 jsonString, err := json.Marshal(endpoint) 169 if err != nil { 170 return nil, err 171 } 172 err = hnsCall("POST", "/endpoints/"+endpoint.Id, string(jsonString), &endpoint) 173 174 return endpoint, err 175} 176 177// ContainerHotAttach attaches an endpoint to a running container 178func (endpoint *HNSEndpoint) ContainerHotAttach(containerID string) error { 179 operation := "ContainerHotAttach" 180 title := "HCSShim::HNSEndpoint::" + operation 181 logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID) 182 183 return modifyNetworkEndpoint(containerID, endpoint.Id, Add) 184} 185 186// ContainerHotDetach detaches an endpoint from a running container 187func (endpoint *HNSEndpoint) ContainerHotDetach(containerID string) error { 188 operation := "ContainerHotDetach" 189 title := "HCSShim::HNSEndpoint::" + operation 190 logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID) 191 192 return modifyNetworkEndpoint(containerID, endpoint.Id, Remove) 193} 194 195// ApplyACLPolicy applies Acl Policy on the Endpoint 196func (endpoint *HNSEndpoint) ApplyACLPolicy(policy *ACLPolicy) error { 197 operation := "ApplyACLPolicy" 198 title := "HCSShim::HNSEndpoint::" + operation 199 logrus.Debugf(title+" id=%s", endpoint.Id) 200 201 jsonString, err := json.Marshal(policy) 202 if err != nil { 203 return err 204 } 205 endpoint.Policies[0] = jsonString 206 _, err = endpoint.Update() 207 return err 208} 209 210// ContainerAttach attaches an endpoint to container 211func (endpoint *HNSEndpoint) ContainerAttach(containerID string, compartmentID uint16) error { 212 operation := "ContainerAttach" 213 title := "HCSShim::HNSEndpoint::" + operation 214 logrus.Debugf(title+" id=%s", endpoint.Id) 215 216 requestMessage := &EndpointAttachDetachRequest{ 217 ContainerID: containerID, 218 CompartmentID: compartmentID, 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+"/attach", string(jsonString), &response) 227} 228 229// ContainerDetach detaches an endpoint from container 230func (endpoint *HNSEndpoint) ContainerDetach(containerID string) error { 231 operation := "ContainerDetach" 232 title := "HCSShim::HNSEndpoint::" + operation 233 logrus.Debugf(title+" id=%s", endpoint.Id) 234 235 requestMessage := &EndpointAttachDetachRequest{ 236 ContainerID: containerID, 237 SystemType: ContainerType, 238 } 239 response := &EndpointResquestResponse{} 240 241 jsonString, err := json.Marshal(requestMessage) 242 if err != nil { 243 return err 244 } 245 return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) 246} 247 248// HostAttach attaches a nic on the host 249func (endpoint *HNSEndpoint) HostAttach(compartmentID uint16) error { 250 operation := "HostAttach" 251 title := "HCSShim::HNSEndpoint::" + operation 252 logrus.Debugf(title+" id=%s", endpoint.Id) 253 requestMessage := &EndpointAttachDetachRequest{ 254 CompartmentID: compartmentID, 255 SystemType: HostType, 256 } 257 response := &EndpointResquestResponse{} 258 259 jsonString, err := json.Marshal(requestMessage) 260 if err != nil { 261 return err 262 } 263 return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) 264 265} 266 267// HostDetach detaches a nic on the host 268func (endpoint *HNSEndpoint) HostDetach() error { 269 operation := "HostDetach" 270 title := "HCSShim::HNSEndpoint::" + operation 271 logrus.Debugf(title+" id=%s", endpoint.Id) 272 requestMessage := &EndpointAttachDetachRequest{ 273 SystemType: HostType, 274 } 275 response := &EndpointResquestResponse{} 276 277 jsonString, err := json.Marshal(requestMessage) 278 if err != nil { 279 return err 280 } 281 return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) 282} 283 284// VirtualMachineNICAttach attaches a endpoint to a virtual machine 285func (endpoint *HNSEndpoint) VirtualMachineNICAttach(virtualMachineNICName string) error { 286 operation := "VirtualMachineNicAttach" 287 title := "HCSShim::HNSEndpoint::" + operation 288 logrus.Debugf(title+" id=%s", endpoint.Id) 289 requestMessage := &EndpointAttachDetachRequest{ 290 VirtualNICName: virtualMachineNICName, 291 SystemType: VirtualMachineType, 292 } 293 response := &EndpointResquestResponse{} 294 295 jsonString, err := json.Marshal(requestMessage) 296 if err != nil { 297 return err 298 } 299 return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) 300} 301 302// VirtualMachineNICDetach detaches a endpoint from a virtual machine 303func (endpoint *HNSEndpoint) VirtualMachineNICDetach() error { 304 operation := "VirtualMachineNicDetach" 305 title := "HCSShim::HNSEndpoint::" + operation 306 logrus.Debugf(title+" id=%s", endpoint.Id) 307 308 requestMessage := &EndpointAttachDetachRequest{ 309 SystemType: VirtualMachineType, 310 } 311 response := &EndpointResquestResponse{} 312 313 jsonString, err := json.Marshal(requestMessage) 314 if err != nil { 315 return err 316 } 317 return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) 318} 319