1
2
3 package hcn
4
5 import (
6 "encoding/json"
7 "errors"
8
9 "github.com/Microsoft/go-winio/pkg/guid"
10 "github.com/Microsoft/hcsshim/internal/interop"
11 "github.com/sirupsen/logrus"
12 )
13
14
15 type IpConfig struct {
16 IpAddress string `json:",omitempty"`
17 PrefixLength uint8 `json:",omitempty"`
18 }
19
20
21 type EndpointFlags uint32
22
23 var (
24
25 EndpointFlagsNone EndpointFlags
26
27 EndpointFlagsRemoteEndpoint EndpointFlags = 1
28 )
29
30
31 type HostComputeEndpoint struct {
32 Id string `json:"ID,omitempty"`
33 Name string `json:",omitempty"`
34 HostComputeNetwork string `json:",omitempty"`
35 HostComputeNamespace string `json:",omitempty"`
36 Policies []EndpointPolicy `json:",omitempty"`
37 IpConfigurations []IpConfig `json:",omitempty"`
38 Dns Dns `json:",omitempty"`
39 Routes []Route `json:",omitempty"`
40 MacAddress string `json:",omitempty"`
41 Flags EndpointFlags `json:",omitempty"`
42 Health Health `json:",omitempty"`
43 SchemaVersion SchemaVersion `json:",omitempty"`
44 }
45
46
47 type EndpointResourceType string
48
49 var (
50
51 EndpointResourceTypePolicy EndpointResourceType = "Policy"
52
53 EndpointResourceTypePort EndpointResourceType = "Port"
54 )
55
56
57
58 type ModifyEndpointSettingRequest struct {
59 ResourceType EndpointResourceType `json:",omitempty"`
60 RequestType RequestType `json:",omitempty"`
61 Settings json.RawMessage `json:",omitempty"`
62 }
63
64
65 type VmEndpointRequest struct {
66 PortId guid.GUID `json:",omitempty"`
67 VirtualNicName string `json:",omitempty"`
68 VirtualMachineId guid.GUID `json:",omitempty"`
69 }
70
71 type PolicyEndpointRequest struct {
72 Policies []EndpointPolicy `json:",omitempty"`
73 }
74
75 func getEndpoint(endpointGUID guid.GUID, query string) (*HostComputeEndpoint, error) {
76
77 var (
78 endpointHandle hcnEndpoint
79 resultBuffer *uint16
80 propertiesBuffer *uint16
81 )
82 hr := hcnOpenEndpoint(&endpointGUID, &endpointHandle, &resultBuffer)
83 if err := checkForErrors("hcnOpenEndpoint", hr, resultBuffer); err != nil {
84 return nil, err
85 }
86
87 hr = hcnQueryEndpointProperties(endpointHandle, query, &propertiesBuffer, &resultBuffer)
88 if err := checkForErrors("hcnQueryEndpointProperties", hr, resultBuffer); err != nil {
89 return nil, err
90 }
91 properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
92
93 hr = hcnCloseEndpoint(endpointHandle)
94 if err := checkForErrors("hcnCloseEndpoint", hr, nil); err != nil {
95 return nil, err
96 }
97
98 var outputEndpoint HostComputeEndpoint
99 if err := json.Unmarshal([]byte(properties), &outputEndpoint); err != nil {
100 return nil, err
101 }
102 return &outputEndpoint, nil
103 }
104
105 func enumerateEndpoints(query string) ([]HostComputeEndpoint, error) {
106
107 var (
108 resultBuffer *uint16
109 endpointBuffer *uint16
110 )
111 hr := hcnEnumerateEndpoints(query, &endpointBuffer, &resultBuffer)
112 if err := checkForErrors("hcnEnumerateEndpoints", hr, resultBuffer); err != nil {
113 return nil, err
114 }
115
116 endpoints := interop.ConvertAndFreeCoTaskMemString(endpointBuffer)
117 var endpointIds []guid.GUID
118 err := json.Unmarshal([]byte(endpoints), &endpointIds)
119 if err != nil {
120 return nil, err
121 }
122
123 var outputEndpoints []HostComputeEndpoint
124 for _, endpointGUID := range endpointIds {
125 endpoint, err := getEndpoint(endpointGUID, query)
126 if err != nil {
127 return nil, err
128 }
129 outputEndpoints = append(outputEndpoints, *endpoint)
130 }
131 return outputEndpoints, nil
132 }
133
134 func createEndpoint(networkID string, endpointSettings string) (*HostComputeEndpoint, error) {
135 networkGUID, err := guid.FromString(networkID)
136 if err != nil {
137 return nil, errInvalidNetworkID
138 }
139
140 var networkHandle hcnNetwork
141 var resultBuffer *uint16
142 hr := hcnOpenNetwork(&networkGUID, &networkHandle, &resultBuffer)
143 if err := checkForErrors("hcnOpenNetwork", hr, resultBuffer); err != nil {
144 return nil, err
145 }
146
147 endpointID := guid.GUID{}
148 var endpointHandle hcnEndpoint
149 hr = hcnCreateEndpoint(networkHandle, &endpointID, endpointSettings, &endpointHandle, &resultBuffer)
150 if err := checkForErrors("hcnCreateEndpoint", hr, resultBuffer); err != nil {
151 return nil, err
152 }
153
154 hcnQuery := defaultQuery()
155 query, err := json.Marshal(hcnQuery)
156 if err != nil {
157 return nil, err
158 }
159 var propertiesBuffer *uint16
160 hr = hcnQueryEndpointProperties(endpointHandle, string(query), &propertiesBuffer, &resultBuffer)
161 if err := checkForErrors("hcnQueryEndpointProperties", hr, resultBuffer); err != nil {
162 return nil, err
163 }
164 properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
165
166 hr = hcnCloseEndpoint(endpointHandle)
167 if err := checkForErrors("hcnCloseEndpoint", hr, nil); err != nil {
168 return nil, err
169 }
170
171 hr = hcnCloseNetwork(networkHandle)
172 if err := checkForErrors("hcnCloseNetwork", hr, nil); err != nil {
173 return nil, err
174 }
175
176 var outputEndpoint HostComputeEndpoint
177 if err := json.Unmarshal([]byte(properties), &outputEndpoint); err != nil {
178 return nil, err
179 }
180 return &outputEndpoint, nil
181 }
182
183 func modifyEndpoint(endpointID string, settings string) (*HostComputeEndpoint, error) {
184 endpointGUID, err := guid.FromString(endpointID)
185 if err != nil {
186 return nil, errInvalidEndpointID
187 }
188
189 var (
190 endpointHandle hcnEndpoint
191 resultBuffer *uint16
192 propertiesBuffer *uint16
193 )
194 hr := hcnOpenEndpoint(&endpointGUID, &endpointHandle, &resultBuffer)
195 if err := checkForErrors("hcnOpenEndpoint", hr, resultBuffer); err != nil {
196 return nil, err
197 }
198
199 hr = hcnModifyEndpoint(endpointHandle, settings, &resultBuffer)
200 if err := checkForErrors("hcnModifyEndpoint", hr, resultBuffer); err != nil {
201 return nil, err
202 }
203
204 hcnQuery := defaultQuery()
205 query, err := json.Marshal(hcnQuery)
206 if err != nil {
207 return nil, err
208 }
209 hr = hcnQueryEndpointProperties(endpointHandle, string(query), &propertiesBuffer, &resultBuffer)
210 if err := checkForErrors("hcnQueryEndpointProperties", hr, resultBuffer); err != nil {
211 return nil, err
212 }
213 properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer)
214
215 hr = hcnCloseEndpoint(endpointHandle)
216 if err := checkForErrors("hcnCloseEndpoint", hr, nil); err != nil {
217 return nil, err
218 }
219
220 var outputEndpoint HostComputeEndpoint
221 if err := json.Unmarshal([]byte(properties), &outputEndpoint); err != nil {
222 return nil, err
223 }
224 return &outputEndpoint, nil
225 }
226
227 func deleteEndpoint(endpointID string) error {
228 endpointGUID, err := guid.FromString(endpointID)
229 if err != nil {
230 return errInvalidEndpointID
231 }
232 var resultBuffer *uint16
233 hr := hcnDeleteEndpoint(&endpointGUID, &resultBuffer)
234 if err := checkForErrors("hcnDeleteEndpoint", hr, resultBuffer); err != nil {
235 return err
236 }
237 return nil
238 }
239
240
241 func ListEndpoints() ([]HostComputeEndpoint, error) {
242 hcnQuery := defaultQuery()
243 endpoints, err := ListEndpointsQuery(hcnQuery)
244 if err != nil {
245 return nil, err
246 }
247 return endpoints, nil
248 }
249
250
251 func ListEndpointsQuery(query HostComputeQuery) ([]HostComputeEndpoint, error) {
252 queryJSON, err := json.Marshal(query)
253 if err != nil {
254 return nil, err
255 }
256
257 endpoints, err := enumerateEndpoints(string(queryJSON))
258 if err != nil {
259 return nil, err
260 }
261 return endpoints, nil
262 }
263
264
265 func ListEndpointsOfNetwork(networkID string) ([]HostComputeEndpoint, error) {
266 hcnQuery := defaultQuery()
267
268 mapA := map[string]string{"VirtualNetwork": networkID}
269 filter, err := json.Marshal(mapA)
270 if err != nil {
271 return nil, err
272 }
273 hcnQuery.Filter = string(filter)
274
275 return ListEndpointsQuery(hcnQuery)
276 }
277
278
279 func GetEndpointByID(endpointID string) (*HostComputeEndpoint, error) {
280 hcnQuery := defaultQuery()
281 mapA := map[string]string{"ID": endpointID}
282 filter, err := json.Marshal(mapA)
283 if err != nil {
284 return nil, err
285 }
286 hcnQuery.Filter = string(filter)
287
288 endpoints, err := ListEndpointsQuery(hcnQuery)
289 if err != nil {
290 return nil, err
291 }
292 if len(endpoints) == 0 {
293 return nil, EndpointNotFoundError{EndpointID: endpointID}
294 }
295 return &endpoints[0], err
296 }
297
298
299 func GetEndpointByName(endpointName string) (*HostComputeEndpoint, error) {
300 hcnQuery := defaultQuery()
301 mapA := map[string]string{"Name": endpointName}
302 filter, err := json.Marshal(mapA)
303 if err != nil {
304 return nil, err
305 }
306 hcnQuery.Filter = string(filter)
307
308 endpoints, err := ListEndpointsQuery(hcnQuery)
309 if err != nil {
310 return nil, err
311 }
312 if len(endpoints) == 0 {
313 return nil, EndpointNotFoundError{EndpointName: endpointName}
314 }
315 return &endpoints[0], err
316 }
317
318
319 func (endpoint *HostComputeEndpoint) Create() (*HostComputeEndpoint, error) {
320 logrus.Debugf("hcn::HostComputeEndpoint::Create id=%s", endpoint.Id)
321
322 if endpoint.HostComputeNamespace != "" {
323 return nil, errors.New("endpoint create error, endpoint json HostComputeNamespace is read only and should not be set")
324 }
325
326 jsonString, err := json.Marshal(endpoint)
327 if err != nil {
328 return nil, err
329 }
330
331 logrus.Debugf("hcn::HostComputeEndpoint::Create JSON: %s", jsonString)
332 endpoint, hcnErr := createEndpoint(endpoint.HostComputeNetwork, string(jsonString))
333 if hcnErr != nil {
334 return nil, hcnErr
335 }
336 return endpoint, nil
337 }
338
339
340 func (endpoint *HostComputeEndpoint) Delete() error {
341 logrus.Debugf("hcn::HostComputeEndpoint::Delete id=%s", endpoint.Id)
342
343 if err := deleteEndpoint(endpoint.Id); err != nil {
344 return err
345 }
346 return nil
347 }
348
349
350 func ModifyEndpointSettings(endpointID string, request *ModifyEndpointSettingRequest) error {
351 logrus.Debugf("hcn::HostComputeEndpoint::ModifyEndpointSettings id=%s", endpointID)
352
353 endpointSettingsRequest, err := json.Marshal(request)
354 if err != nil {
355 return err
356 }
357
358 _, err = modifyEndpoint(endpointID, string(endpointSettingsRequest))
359 if err != nil {
360 return err
361 }
362 return nil
363 }
364
365
366 func (endpoint *HostComputeEndpoint) ApplyPolicy(requestType RequestType, endpointPolicy PolicyEndpointRequest) error {
367 logrus.Debugf("hcn::HostComputeEndpoint::ApplyPolicy id=%s", endpoint.Id)
368
369 settingsJSON, err := json.Marshal(endpointPolicy)
370 if err != nil {
371 return err
372 }
373 requestMessage := &ModifyEndpointSettingRequest{
374 ResourceType: EndpointResourceTypePolicy,
375 RequestType: requestType,
376 Settings: settingsJSON,
377 }
378
379 return ModifyEndpointSettings(endpoint.Id, requestMessage)
380 }
381
382
383 func (endpoint *HostComputeEndpoint) NamespaceAttach(namespaceID string) error {
384 return AddNamespaceEndpoint(namespaceID, endpoint.Id)
385 }
386
387
388 func (endpoint *HostComputeEndpoint) NamespaceDetach(namespaceID string) error {
389 return RemoveNamespaceEndpoint(namespaceID, endpoint.Id)
390 }
391
View as plain text