package hcsshim import ( "encoding/json" "fmt" "net" "github.com/sirupsen/logrus" ) // HNSEndpoint represents a network endpoint in HNS type HNSEndpoint struct { Id string `json:"ID,omitempty"` Name string `json:",omitempty"` VirtualNetwork string `json:",omitempty"` VirtualNetworkName string `json:",omitempty"` Policies []json.RawMessage `json:",omitempty"` MacAddress string `json:",omitempty"` IPAddress net.IP `json:",omitempty"` DNSSuffix string `json:",omitempty"` DNSServerList string `json:",omitempty"` GatewayAddress string `json:",omitempty"` EnableInternalDNS bool `json:",omitempty"` DisableICC bool `json:",omitempty"` PrefixLength uint8 `json:",omitempty"` IsRemoteEndpoint bool `json:",omitempty"` } //SystemType represents the type of the system on which actions are done type SystemType string // SystemType const const ( ContainerType SystemType = "Container" VirtualMachineType SystemType = "VirtualMachine" HostType SystemType = "Host" ) // EndpointAttachDetachRequest is the structure used to send request to the container to modify the system // Supported resource types are Network and Request Types are Add/Remove type EndpointAttachDetachRequest struct { ContainerID string `json:"ContainerId,omitempty"` SystemType SystemType `json:"SystemType"` CompartmentID uint16 `json:"CompartmentId,omitempty"` VirtualNICName string `json:"VirtualNicName,omitempty"` } // EndpointResquestResponse is object to get the endpoint request response type EndpointResquestResponse struct { Success bool Error string } // HNSEndpointRequest makes a HNS call to modify/query a network endpoint func HNSEndpointRequest(method, path, request string) (*HNSEndpoint, error) { endpoint := &HNSEndpoint{} err := hnsCall(method, "/endpoints/"+path, request, &endpoint) if err != nil { return nil, err } return endpoint, nil } // HNSListEndpointRequest makes a HNS call to query the list of available endpoints func HNSListEndpointRequest() ([]HNSEndpoint, error) { var endpoint []HNSEndpoint err := hnsCall("GET", "/endpoints/", "", &endpoint) if err != nil { return nil, err } return endpoint, nil } // HotAttachEndpoint makes a HCS Call to attach the endpoint to the container func HotAttachEndpoint(containerID string, endpointID string) error { return modifyNetworkEndpoint(containerID, endpointID, Add) } // HotDetachEndpoint makes a HCS Call to detach the endpoint from the container func HotDetachEndpoint(containerID string, endpointID string) error { return modifyNetworkEndpoint(containerID, endpointID, Remove) } // ModifyContainer corresponding to the container id, by sending a request func modifyContainer(id string, request *ResourceModificationRequestResponse) error { container, err := OpenContainer(id) if err != nil { if IsNotExist(err) { return ErrComputeSystemDoesNotExist } return getInnerError(err) } defer container.Close() err = container.Modify(request) if err != nil { if IsNotSupported(err) { return ErrPlatformNotSupported } return getInnerError(err) } return nil } func modifyNetworkEndpoint(containerID string, endpointID string, request RequestType) error { requestMessage := &ResourceModificationRequestResponse{ Resource: Network, Request: request, Data: endpointID, } err := modifyContainer(containerID, requestMessage) if err != nil { return err } return nil } // GetHNSEndpointByID get the Endpoint by ID func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) { return HNSEndpointRequest("GET", endpointID, "") } // GetHNSEndpointByName gets the endpoint filtered by Name func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) { hnsResponse, err := HNSListEndpointRequest() if err != nil { return nil, err } for _, hnsEndpoint := range hnsResponse { if hnsEndpoint.Name == endpointName { return &hnsEndpoint, nil } } return nil, fmt.Errorf("Endpoint %v not found", endpointName) } // Create Endpoint by sending EndpointRequest to HNS. TODO: Create a separate HNS interface to place all these methods func (endpoint *HNSEndpoint) Create() (*HNSEndpoint, error) { operation := "Create" title := "HCSShim::HNSEndpoint::" + operation logrus.Debugf(title+" id=%s", endpoint.Id) jsonString, err := json.Marshal(endpoint) if err != nil { return nil, err } return HNSEndpointRequest("POST", "", string(jsonString)) } // Delete Endpoint by sending EndpointRequest to HNS func (endpoint *HNSEndpoint) Delete() (*HNSEndpoint, error) { operation := "Delete" title := "HCSShim::HNSEndpoint::" + operation logrus.Debugf(title+" id=%s", endpoint.Id) return HNSEndpointRequest("DELETE", endpoint.Id, "") } // Update Endpoint func (endpoint *HNSEndpoint) Update() (*HNSEndpoint, error) { operation := "Update" title := "HCSShim::HNSEndpoint::" + operation logrus.Debugf(title+" id=%s", endpoint.Id) jsonString, err := json.Marshal(endpoint) if err != nil { return nil, err } err = hnsCall("POST", "/endpoints/"+endpoint.Id, string(jsonString), &endpoint) return endpoint, err } // ContainerHotAttach attaches an endpoint to a running container func (endpoint *HNSEndpoint) ContainerHotAttach(containerID string) error { operation := "ContainerHotAttach" title := "HCSShim::HNSEndpoint::" + operation logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID) return modifyNetworkEndpoint(containerID, endpoint.Id, Add) } // ContainerHotDetach detaches an endpoint from a running container func (endpoint *HNSEndpoint) ContainerHotDetach(containerID string) error { operation := "ContainerHotDetach" title := "HCSShim::HNSEndpoint::" + operation logrus.Debugf(title+" id=%s, containerId=%s", endpoint.Id, containerID) return modifyNetworkEndpoint(containerID, endpoint.Id, Remove) } // ApplyACLPolicy applies Acl Policy on the Endpoint func (endpoint *HNSEndpoint) ApplyACLPolicy(policy *ACLPolicy) error { operation := "ApplyACLPolicy" title := "HCSShim::HNSEndpoint::" + operation logrus.Debugf(title+" id=%s", endpoint.Id) jsonString, err := json.Marshal(policy) if err != nil { return err } endpoint.Policies[0] = jsonString _, err = endpoint.Update() return err } // ContainerAttach attaches an endpoint to container func (endpoint *HNSEndpoint) ContainerAttach(containerID string, compartmentID uint16) error { operation := "ContainerAttach" title := "HCSShim::HNSEndpoint::" + operation logrus.Debugf(title+" id=%s", endpoint.Id) requestMessage := &EndpointAttachDetachRequest{ ContainerID: containerID, CompartmentID: compartmentID, SystemType: ContainerType, } response := &EndpointResquestResponse{} jsonString, err := json.Marshal(requestMessage) if err != nil { return err } return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) } // ContainerDetach detaches an endpoint from container func (endpoint *HNSEndpoint) ContainerDetach(containerID string) error { operation := "ContainerDetach" title := "HCSShim::HNSEndpoint::" + operation logrus.Debugf(title+" id=%s", endpoint.Id) requestMessage := &EndpointAttachDetachRequest{ ContainerID: containerID, SystemType: ContainerType, } response := &EndpointResquestResponse{} jsonString, err := json.Marshal(requestMessage) if err != nil { return err } return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) } // HostAttach attaches a nic on the host func (endpoint *HNSEndpoint) HostAttach(compartmentID uint16) error { operation := "HostAttach" title := "HCSShim::HNSEndpoint::" + operation logrus.Debugf(title+" id=%s", endpoint.Id) requestMessage := &EndpointAttachDetachRequest{ CompartmentID: compartmentID, SystemType: HostType, } response := &EndpointResquestResponse{} jsonString, err := json.Marshal(requestMessage) if err != nil { return err } return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) } // HostDetach detaches a nic on the host func (endpoint *HNSEndpoint) HostDetach() error { operation := "HostDetach" title := "HCSShim::HNSEndpoint::" + operation logrus.Debugf(title+" id=%s", endpoint.Id) requestMessage := &EndpointAttachDetachRequest{ SystemType: HostType, } response := &EndpointResquestResponse{} jsonString, err := json.Marshal(requestMessage) if err != nil { return err } return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) } // VirtualMachineNICAttach attaches a endpoint to a virtual machine func (endpoint *HNSEndpoint) VirtualMachineNICAttach(virtualMachineNICName string) error { operation := "VirtualMachineNicAttach" title := "HCSShim::HNSEndpoint::" + operation logrus.Debugf(title+" id=%s", endpoint.Id) requestMessage := &EndpointAttachDetachRequest{ VirtualNICName: virtualMachineNICName, SystemType: VirtualMachineType, } response := &EndpointResquestResponse{} jsonString, err := json.Marshal(requestMessage) if err != nil { return err } return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) } // VirtualMachineNICDetach detaches a endpoint from a virtual machine func (endpoint *HNSEndpoint) VirtualMachineNICDetach() error { operation := "VirtualMachineNicDetach" title := "HCSShim::HNSEndpoint::" + operation logrus.Debugf(title+" id=%s", endpoint.Id) requestMessage := &EndpointAttachDetachRequest{ SystemType: VirtualMachineType, } response := &EndpointResquestResponse{} jsonString, err := json.Marshal(requestMessage) if err != nil { return err } return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) }