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