1package hns 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 Namespace *Namespace `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// GetHNSEndpointByID get the Endpoint by ID 77func GetHNSEndpointByID(endpointID string) (*HNSEndpoint, error) { 78 return HNSEndpointRequest("GET", endpointID, "") 79} 80 81// GetHNSEndpointByName gets the endpoint filtered by Name 82func GetHNSEndpointByName(endpointName string) (*HNSEndpoint, error) { 83 hnsResponse, err := HNSListEndpointRequest() 84 if err != nil { 85 return nil, err 86 } 87 for _, hnsEndpoint := range hnsResponse { 88 if hnsEndpoint.Name == endpointName { 89 return &hnsEndpoint, nil 90 } 91 } 92 return nil, EndpointNotFoundError{EndpointName: endpointName} 93} 94 95// Create Endpoint by sending EndpointRequest to HNS. TODO: Create a separate HNS interface to place all these methods 96func (endpoint *HNSEndpoint) Create() (*HNSEndpoint, error) { 97 operation := "Create" 98 title := "hcsshim::HNSEndpoint::" + operation 99 logrus.Debugf(title+" id=%s", endpoint.Id) 100 101 jsonString, err := json.Marshal(endpoint) 102 if err != nil { 103 return nil, err 104 } 105 return HNSEndpointRequest("POST", "", string(jsonString)) 106} 107 108// Delete Endpoint by sending EndpointRequest to HNS 109func (endpoint *HNSEndpoint) Delete() (*HNSEndpoint, error) { 110 operation := "Delete" 111 title := "hcsshim::HNSEndpoint::" + operation 112 logrus.Debugf(title+" id=%s", endpoint.Id) 113 114 return HNSEndpointRequest("DELETE", endpoint.Id, "") 115} 116 117// Update Endpoint 118func (endpoint *HNSEndpoint) Update() (*HNSEndpoint, error) { 119 operation := "Update" 120 title := "hcsshim::HNSEndpoint::" + operation 121 logrus.Debugf(title+" id=%s", endpoint.Id) 122 jsonString, err := json.Marshal(endpoint) 123 if err != nil { 124 return nil, err 125 } 126 err = hnsCall("POST", "/endpoints/"+endpoint.Id, string(jsonString), &endpoint) 127 128 return endpoint, err 129} 130 131// ApplyACLPolicy applies a set of ACL Policies on the Endpoint 132func (endpoint *HNSEndpoint) ApplyACLPolicy(policies ...*ACLPolicy) error { 133 operation := "ApplyACLPolicy" 134 title := "hcsshim::HNSEndpoint::" + operation 135 logrus.Debugf(title+" id=%s", endpoint.Id) 136 137 for _, policy := range policies { 138 if policy == nil { 139 continue 140 } 141 jsonString, err := json.Marshal(policy) 142 if err != nil { 143 return err 144 } 145 endpoint.Policies = append(endpoint.Policies, jsonString) 146 } 147 148 _, err := endpoint.Update() 149 return err 150} 151 152// ContainerAttach attaches an endpoint to container 153func (endpoint *HNSEndpoint) ContainerAttach(containerID string, compartmentID uint16) error { 154 operation := "ContainerAttach" 155 title := "hcsshim::HNSEndpoint::" + operation 156 logrus.Debugf(title+" id=%s", endpoint.Id) 157 158 requestMessage := &EndpointAttachDetachRequest{ 159 ContainerID: containerID, 160 CompartmentID: compartmentID, 161 SystemType: ContainerType, 162 } 163 response := &EndpointResquestResponse{} 164 jsonString, err := json.Marshal(requestMessage) 165 if err != nil { 166 return err 167 } 168 return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) 169} 170 171// ContainerDetach detaches an endpoint from container 172func (endpoint *HNSEndpoint) ContainerDetach(containerID string) error { 173 operation := "ContainerDetach" 174 title := "hcsshim::HNSEndpoint::" + operation 175 logrus.Debugf(title+" id=%s", endpoint.Id) 176 177 requestMessage := &EndpointAttachDetachRequest{ 178 ContainerID: containerID, 179 SystemType: ContainerType, 180 } 181 response := &EndpointResquestResponse{} 182 183 jsonString, err := json.Marshal(requestMessage) 184 if err != nil { 185 return err 186 } 187 return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) 188} 189 190// HostAttach attaches a nic on the host 191func (endpoint *HNSEndpoint) HostAttach(compartmentID uint16) error { 192 operation := "HostAttach" 193 title := "hcsshim::HNSEndpoint::" + operation 194 logrus.Debugf(title+" id=%s", endpoint.Id) 195 requestMessage := &EndpointAttachDetachRequest{ 196 CompartmentID: compartmentID, 197 SystemType: HostType, 198 } 199 response := &EndpointResquestResponse{} 200 201 jsonString, err := json.Marshal(requestMessage) 202 if err != nil { 203 return err 204 } 205 return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) 206 207} 208 209// HostDetach detaches a nic on the host 210func (endpoint *HNSEndpoint) HostDetach() error { 211 operation := "HostDetach" 212 title := "hcsshim::HNSEndpoint::" + operation 213 logrus.Debugf(title+" id=%s", endpoint.Id) 214 requestMessage := &EndpointAttachDetachRequest{ 215 SystemType: HostType, 216 } 217 response := &EndpointResquestResponse{} 218 219 jsonString, err := json.Marshal(requestMessage) 220 if err != nil { 221 return err 222 } 223 return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) 224} 225 226// VirtualMachineNICAttach attaches a endpoint to a virtual machine 227func (endpoint *HNSEndpoint) VirtualMachineNICAttach(virtualMachineNICName string) error { 228 operation := "VirtualMachineNicAttach" 229 title := "hcsshim::HNSEndpoint::" + operation 230 logrus.Debugf(title+" id=%s", endpoint.Id) 231 requestMessage := &EndpointAttachDetachRequest{ 232 VirtualNICName: virtualMachineNICName, 233 SystemType: VirtualMachineType, 234 } 235 response := &EndpointResquestResponse{} 236 237 jsonString, err := json.Marshal(requestMessage) 238 if err != nil { 239 return err 240 } 241 return hnsCall("POST", "/endpoints/"+endpoint.Id+"/attach", string(jsonString), &response) 242} 243 244// VirtualMachineNICDetach detaches a endpoint from a virtual machine 245func (endpoint *HNSEndpoint) VirtualMachineNICDetach() error { 246 operation := "VirtualMachineNicDetach" 247 title := "hcsshim::HNSEndpoint::" + operation 248 logrus.Debugf(title+" id=%s", endpoint.Id) 249 250 requestMessage := &EndpointAttachDetachRequest{ 251 SystemType: VirtualMachineType, 252 } 253 response := &EndpointResquestResponse{} 254 255 jsonString, err := json.Marshal(requestMessage) 256 if err != nil { 257 return err 258 } 259 return hnsCall("POST", "/endpoints/"+endpoint.Id+"/detach", string(jsonString), &response) 260} 261