1package hcn 2 3import ( 4 "encoding/json" 5 6 "github.com/Microsoft/hcsshim/internal/guid" 7 "github.com/Microsoft/hcsshim/internal/interop" 8 "github.com/sirupsen/logrus" 9) 10 11// Route is assoicated with a subnet. 12type Route struct { 13 NextHop string `json:",omitempty"` 14 DestinationPrefix string `json:",omitempty"` 15 Metric uint16 `json:",omitempty"` 16} 17 18// Subnet is assoicated with a Ipam. 19type Subnet struct { 20 IpAddressPrefix string `json:",omitempty"` 21 Policies []json.RawMessage `json:",omitempty"` 22 Routes []Route `json:",omitempty"` 23} 24 25// Ipam (Internet Protocol Addres Management) is assoicated with a network 26// and represents the address space(s) of a network. 27type Ipam struct { 28 Type string `json:",omitempty"` // Ex: Static, DHCP 29 Subnets []Subnet `json:",omitempty"` 30} 31 32// MacRange is associated with MacPool and respresents the start and end addresses. 33type MacRange struct { 34 StartMacAddress string `json:",omitempty"` 35 EndMacAddress string `json:",omitempty"` 36} 37 38// MacPool is assoicated with a network and represents pool of MacRanges. 39type MacPool struct { 40 Ranges []MacRange `json:",omitempty"` 41} 42 43// Dns (Domain Name System is associated with a network. 44type Dns struct { 45 Domain string `json:",omitempty"` 46 Search []string `json:",omitempty"` 47 ServerList []string `json:",omitempty"` 48 Options []string `json:",omitempty"` 49} 50 51// NetworkType are various networks. 52type NetworkType string 53 54// NetworkType const 55const ( 56 NAT NetworkType = "NAT" 57 Transparent NetworkType = "Transparent" 58 L2Bridge NetworkType = "L2Bridge" 59 L2Tunnel NetworkType = "L2Tunnel" 60 ICS NetworkType = "ICS" 61 Private NetworkType = "Private" 62 Overlay NetworkType = "Overlay" 63) 64 65// NetworkFlags are various network flags. 66type NetworkFlags uint32 67 68// NetworkFlags const 69const ( 70 None NetworkFlags = 0 71 EnableNonPersistent NetworkFlags = 8 72) 73 74// HostComputeNetwork represents a network 75type HostComputeNetwork struct { 76 Id string `json:"ID,omitempty"` 77 Name string `json:",omitempty"` 78 Type NetworkType `json:",omitempty"` 79 Policies []NetworkPolicy `json:",omitempty"` 80 MacPool MacPool `json:",omitempty"` 81 Dns Dns `json:",omitempty"` 82 Ipams []Ipam `json:",omitempty"` 83 Flags NetworkFlags `json:",omitempty"` // 0: None 84 SchemaVersion SchemaVersion `json:",omitempty"` 85} 86 87// NetworkResourceType are the 3 different Network settings resources. 88type NetworkResourceType string 89 90var ( 91 // NetworkResourceTypePolicy is for Network's policies. Ex: RemoteSubnet 92 NetworkResourceTypePolicy NetworkResourceType = "Policy" 93 // NetworkResourceTypeDNS is for Network's DNS settings. 94 NetworkResourceTypeDNS NetworkResourceType = "DNS" 95 // NetworkResourceTypeExtension is for Network's extension settings. 96 NetworkResourceTypeExtension NetworkResourceType = "Extension" 97) 98 99// ModifyNetworkSettingRequest is the structure used to send request to modify an network. 100// Used to update DNS/extension/policy on an network. 101type ModifyNetworkSettingRequest struct { 102 ResourceType NetworkResourceType `json:",omitempty"` // Policy, DNS, Extension 103 RequestType RequestType `json:",omitempty"` // Add, Remove, Update, Refresh 104 Settings json.RawMessage `json:",omitempty"` 105} 106 107type PolicyNetworkRequest struct { 108 Policies []NetworkPolicy `json:",omitempty"` 109} 110 111func getNetwork(networkGuid guid.GUID, query string) (*HostComputeNetwork, error) { 112 // Open network. 113 var ( 114 networkHandle hcnNetwork 115 resultBuffer *uint16 116 propertiesBuffer *uint16 117 ) 118 hr := hcnOpenNetwork(&networkGuid, &networkHandle, &resultBuffer) 119 if err := checkForErrors("hcnOpenNetwork", hr, resultBuffer); err != nil { 120 return nil, err 121 } 122 // Query network. 123 hr = hcnQueryNetworkProperties(networkHandle, query, &propertiesBuffer, &resultBuffer) 124 if err := checkForErrors("hcnQueryNetworkProperties", hr, resultBuffer); err != nil { 125 return nil, err 126 } 127 properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer) 128 // Close network. 129 hr = hcnCloseNetwork(networkHandle) 130 if err := checkForErrors("hcnCloseNetwork", hr, nil); err != nil { 131 return nil, err 132 } 133 // Convert output to HostComputeNetwork 134 var outputNetwork HostComputeNetwork 135 if err := json.Unmarshal([]byte(properties), &outputNetwork); err != nil { 136 return nil, err 137 } 138 return &outputNetwork, nil 139} 140 141func enumerateNetworks(query string) ([]HostComputeNetwork, error) { 142 // Enumerate all Network Guids 143 var ( 144 resultBuffer *uint16 145 networkBuffer *uint16 146 ) 147 hr := hcnEnumerateNetworks(query, &networkBuffer, &resultBuffer) 148 if err := checkForErrors("hcnEnumerateNetworks", hr, resultBuffer); err != nil { 149 return nil, err 150 } 151 152 networks := interop.ConvertAndFreeCoTaskMemString(networkBuffer) 153 var networkIds []guid.GUID 154 if err := json.Unmarshal([]byte(networks), &networkIds); err != nil { 155 return nil, err 156 } 157 158 var outputNetworks []HostComputeNetwork 159 for _, networkGuid := range networkIds { 160 network, err := getNetwork(networkGuid, query) 161 if err != nil { 162 return nil, err 163 } 164 outputNetworks = append(outputNetworks, *network) 165 } 166 return outputNetworks, nil 167} 168 169func createNetwork(settings string) (*HostComputeNetwork, error) { 170 // Create new network. 171 var ( 172 networkHandle hcnNetwork 173 resultBuffer *uint16 174 propertiesBuffer *uint16 175 ) 176 networkGuid := guid.GUID{} 177 hr := hcnCreateNetwork(&networkGuid, settings, &networkHandle, &resultBuffer) 178 if err := checkForErrors("hcnCreateNetwork", hr, resultBuffer); err != nil { 179 return nil, err 180 } 181 // Query network. 182 hcnQuery := defaultQuery() 183 query, err := json.Marshal(hcnQuery) 184 if err != nil { 185 return nil, err 186 } 187 hr = hcnQueryNetworkProperties(networkHandle, string(query), &propertiesBuffer, &resultBuffer) 188 if err := checkForErrors("hcnQueryNetworkProperties", hr, resultBuffer); err != nil { 189 return nil, err 190 } 191 properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer) 192 // Close network. 193 hr = hcnCloseNetwork(networkHandle) 194 if err := checkForErrors("hcnCloseNetwork", hr, nil); err != nil { 195 return nil, err 196 } 197 // Convert output to HostComputeNetwork 198 var outputNetwork HostComputeNetwork 199 if err := json.Unmarshal([]byte(properties), &outputNetwork); err != nil { 200 return nil, err 201 } 202 return &outputNetwork, nil 203} 204 205func modifyNetwork(networkId string, settings string) (*HostComputeNetwork, error) { 206 networkGuid := guid.FromString(networkId) 207 // Open Network 208 var ( 209 networkHandle hcnNetwork 210 resultBuffer *uint16 211 propertiesBuffer *uint16 212 ) 213 hr := hcnOpenNetwork(&networkGuid, &networkHandle, &resultBuffer) 214 if err := checkForErrors("hcnOpenNetwork", hr, resultBuffer); err != nil { 215 return nil, err 216 } 217 // Modify Network 218 hr = hcnModifyNetwork(networkHandle, settings, &resultBuffer) 219 if err := checkForErrors("hcnModifyNetwork", hr, resultBuffer); err != nil { 220 return nil, err 221 } 222 // Query network. 223 hcnQuery := defaultQuery() 224 query, err := json.Marshal(hcnQuery) 225 if err != nil { 226 return nil, err 227 } 228 hr = hcnQueryNetworkProperties(networkHandle, string(query), &propertiesBuffer, &resultBuffer) 229 if err := checkForErrors("hcnQueryNetworkProperties", hr, resultBuffer); err != nil { 230 return nil, err 231 } 232 properties := interop.ConvertAndFreeCoTaskMemString(propertiesBuffer) 233 // Close network. 234 hr = hcnCloseNetwork(networkHandle) 235 if err := checkForErrors("hcnCloseNetwork", hr, nil); err != nil { 236 return nil, err 237 } 238 // Convert output to HostComputeNetwork 239 var outputNetwork HostComputeNetwork 240 if err := json.Unmarshal([]byte(properties), &outputNetwork); err != nil { 241 return nil, err 242 } 243 return &outputNetwork, nil 244} 245 246func deleteNetwork(networkId string) error { 247 networkGuid := guid.FromString(networkId) 248 var resultBuffer *uint16 249 hr := hcnDeleteNetwork(&networkGuid, &resultBuffer) 250 if err := checkForErrors("hcnDeleteNetwork", hr, resultBuffer); err != nil { 251 return err 252 } 253 return nil 254} 255 256// ListNetworks makes a call to list all available networks. 257func ListNetworks() ([]HostComputeNetwork, error) { 258 hcnQuery := defaultQuery() 259 networks, err := ListNetworksQuery(hcnQuery) 260 if err != nil { 261 return nil, err 262 } 263 return networks, nil 264} 265 266// ListNetworksQuery makes a call to query the list of available networks. 267func ListNetworksQuery(query HostComputeQuery) ([]HostComputeNetwork, error) { 268 queryJson, err := json.Marshal(query) 269 if err != nil { 270 return nil, err 271 } 272 273 networks, err := enumerateNetworks(string(queryJson)) 274 if err != nil { 275 return nil, err 276 } 277 return networks, nil 278} 279 280// GetNetworkByID returns the network specified by Id. 281func GetNetworkByID(networkID string) (*HostComputeNetwork, error) { 282 hcnQuery := defaultQuery() 283 mapA := map[string]string{"ID": networkID} 284 filter, err := json.Marshal(mapA) 285 if err != nil { 286 return nil, err 287 } 288 hcnQuery.Filter = string(filter) 289 290 networks, err := ListNetworksQuery(hcnQuery) 291 if err != nil { 292 return nil, err 293 } 294 if len(networks) == 0 { 295 return nil, NetworkNotFoundError{NetworkID: networkID} 296 } 297 return &networks[0], err 298} 299 300// GetNetworkByName returns the network specified by Name. 301func GetNetworkByName(networkName string) (*HostComputeNetwork, error) { 302 hcnQuery := defaultQuery() 303 mapA := map[string]string{"Name": networkName} 304 filter, err := json.Marshal(mapA) 305 if err != nil { 306 return nil, err 307 } 308 hcnQuery.Filter = string(filter) 309 310 networks, err := ListNetworksQuery(hcnQuery) 311 if err != nil { 312 return nil, err 313 } 314 if len(networks) == 0 { 315 return nil, NetworkNotFoundError{NetworkName: networkName} 316 } 317 return &networks[0], err 318} 319 320// Create Network. 321func (network *HostComputeNetwork) Create() (*HostComputeNetwork, error) { 322 logrus.Debugf("hcn::HostComputeNetwork::Create id=%s", network.Id) 323 324 jsonString, err := json.Marshal(network) 325 if err != nil { 326 return nil, err 327 } 328 329 logrus.Debugf("hcn::HostComputeNetwork::Create JSON: %s", jsonString) 330 network, hcnErr := createNetwork(string(jsonString)) 331 if hcnErr != nil { 332 return nil, hcnErr 333 } 334 return network, nil 335} 336 337// Delete Network. 338func (network *HostComputeNetwork) Delete() error { 339 logrus.Debugf("hcn::HostComputeNetwork::Delete id=%s", network.Id) 340 341 if err := deleteNetwork(network.Id); err != nil { 342 return err 343 } 344 return nil 345} 346 347// ModifyNetworkSettings updates the Policy for a network. 348func (network *HostComputeNetwork) ModifyNetworkSettings(request *ModifyNetworkSettingRequest) error { 349 logrus.Debugf("hcn::HostComputeNetwork::ModifyNetworkSettings id=%s", network.Id) 350 351 networkSettingsRequest, err := json.Marshal(request) 352 if err != nil { 353 return err 354 } 355 356 _, err = modifyNetwork(network.Id, string(networkSettingsRequest)) 357 if err != nil { 358 return err 359 } 360 return nil 361} 362 363// AddPolicy applies a Policy (ex: RemoteSubnet) on the Network. 364func (network *HostComputeNetwork) AddPolicy(networkPolicy PolicyNetworkRequest) error { 365 logrus.Debugf("hcn::HostComputeNetwork::AddPolicy id=%s", network.Id) 366 367 settingsJson, err := json.Marshal(networkPolicy) 368 if err != nil { 369 return err 370 } 371 requestMessage := &ModifyNetworkSettingRequest{ 372 ResourceType: NetworkResourceTypePolicy, 373 RequestType: RequestTypeAdd, 374 Settings: settingsJson, 375 } 376 377 return network.ModifyNetworkSettings(requestMessage) 378} 379 380// RemovePolicy removes a Policy (ex: RemoteSubnet) from the Network. 381func (network *HostComputeNetwork) RemovePolicy(networkPolicy PolicyNetworkRequest) error { 382 logrus.Debugf("hcn::HostComputeNetwork::RemovePolicy id=%s", network.Id) 383 384 settingsJson, err := json.Marshal(networkPolicy) 385 if err != nil { 386 return err 387 } 388 requestMessage := &ModifyNetworkSettingRequest{ 389 ResourceType: NetworkResourceTypePolicy, 390 RequestType: RequestTypeRemove, 391 Settings: settingsJson, 392 } 393 394 return network.ModifyNetworkSettings(requestMessage) 395} 396 397// CreateEndpoint creates an endpoint on the Network. 398func (network *HostComputeNetwork) CreateEndpoint(endpoint *HostComputeEndpoint) (*HostComputeEndpoint, error) { 399 isRemote := endpoint.Flags&EndpointFlagsRemoteEndpoint != 0 400 logrus.Debugf("hcn::HostComputeNetwork::CreatEndpoint, networkId=%s remote=%t", network.Id, isRemote) 401 402 endpoint.HostComputeNetwork = network.Id 403 endpointSettings, err := json.Marshal(endpoint) 404 if err != nil { 405 return nil, err 406 } 407 newEndpoint, err := createEndpoint(network.Id, string(endpointSettings)) 408 if err != nil { 409 return nil, err 410 } 411 return newEndpoint, nil 412} 413 414// CreateRemoteEndpoint creates a remote endpoint on the Network. 415func (network *HostComputeNetwork) CreateRemoteEndpoint(endpoint *HostComputeEndpoint) (*HostComputeEndpoint, error) { 416 endpoint.Flags = EndpointFlagsRemoteEndpoint | endpoint.Flags 417 return network.CreateEndpoint(endpoint) 418} 419