1package hcsshim
2
3import (
4	"encoding/json"
5	"fmt"
6	"net"
7
8	"github.com/sirupsen/logrus"
9)
10
11// Subnet is assoicated with a network and represents a list
12// of subnets available to the network
13type Subnet struct {
14	AddressPrefix  string            `json:",omitempty"`
15	GatewayAddress string            `json:",omitempty"`
16	Policies       []json.RawMessage `json:",omitempty"`
17}
18
19// MacPool is assoicated with a network and represents a list
20// of macaddresses available to the network
21type MacPool struct {
22	StartMacAddress string `json:",omitempty"`
23	EndMacAddress   string `json:",omitempty"`
24}
25
26// HNSNetwork represents a network in HNS
27type HNSNetwork struct {
28	Id                   string            `json:"ID,omitempty"`
29	Name                 string            `json:",omitempty"`
30	Type                 string            `json:",omitempty"`
31	NetworkAdapterName   string            `json:",omitempty"`
32	SourceMac            string            `json:",omitempty"`
33	Policies             []json.RawMessage `json:",omitempty"`
34	MacPools             []MacPool         `json:",omitempty"`
35	Subnets              []Subnet          `json:",omitempty"`
36	DNSSuffix            string            `json:",omitempty"`
37	DNSServerList        string            `json:",omitempty"`
38	DNSServerCompartment uint32            `json:",omitempty"`
39	ManagementIP         string            `json:",omitempty"`
40	AutomaticDNS         bool              `json:",omitempty"`
41}
42
43type hnsNetworkResponse struct {
44	Success bool
45	Error   string
46	Output  HNSNetwork
47}
48
49type hnsResponse struct {
50	Success bool
51	Error   string
52	Output  json.RawMessage
53}
54
55// HNSNetworkRequest makes a call into HNS to update/query a single network
56func HNSNetworkRequest(method, path, request string) (*HNSNetwork, error) {
57	var network HNSNetwork
58	err := hnsCall(method, "/networks/"+path, request, &network)
59	if err != nil {
60		return nil, err
61	}
62
63	return &network, nil
64}
65
66// HNSListNetworkRequest makes a HNS call to query the list of available networks
67func HNSListNetworkRequest(method, path, request string) ([]HNSNetwork, error) {
68	var network []HNSNetwork
69	err := hnsCall(method, "/networks/"+path, request, &network)
70	if err != nil {
71		return nil, err
72	}
73
74	return network, nil
75}
76
77// GetHNSNetworkByID
78func GetHNSNetworkByID(networkID string) (*HNSNetwork, error) {
79	return HNSNetworkRequest("GET", networkID, "")
80}
81
82// GetHNSNetworkName filtered by Name
83func GetHNSNetworkByName(networkName string) (*HNSNetwork, error) {
84	hsnnetworks, err := HNSListNetworkRequest("GET", "", "")
85	if err != nil {
86		return nil, err
87	}
88	for _, hnsnetwork := range hsnnetworks {
89		if hnsnetwork.Name == networkName {
90			return &hnsnetwork, nil
91		}
92	}
93	return nil, fmt.Errorf("Network %v not found", networkName)
94}
95
96// Create Network by sending NetworkRequest to HNS.
97func (network *HNSNetwork) Create() (*HNSNetwork, error) {
98	operation := "Create"
99	title := "HCSShim::HNSNetwork::" + operation
100	logrus.Debugf(title+" id=%s", network.Id)
101
102	jsonString, err := json.Marshal(network)
103	if err != nil {
104		return nil, err
105	}
106	return HNSNetworkRequest("POST", "", string(jsonString))
107}
108
109// Delete Network by sending NetworkRequest to HNS
110func (network *HNSNetwork) Delete() (*HNSNetwork, error) {
111	operation := "Delete"
112	title := "HCSShim::HNSNetwork::" + operation
113	logrus.Debugf(title+" id=%s", network.Id)
114
115	return HNSNetworkRequest("DELETE", network.Id, "")
116}
117
118// Creates an endpoint on the Network.
119func (network *HNSNetwork) NewEndpoint(ipAddress net.IP, macAddress net.HardwareAddr) *HNSEndpoint {
120	return &HNSEndpoint{
121		VirtualNetwork: network.Id,
122		IPAddress:      ipAddress,
123		MacAddress:     string(macAddress),
124	}
125}
126
127func (network *HNSNetwork) CreateEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) {
128	operation := "CreateEndpoint"
129	title := "HCSShim::HNSNetwork::" + operation
130	logrus.Debugf(title+" id=%s, endpointId=%s", network.Id, endpoint.Id)
131
132	endpoint.VirtualNetwork = network.Id
133	return endpoint.Create()
134}
135
136func (network *HNSNetwork) CreateRemoteEndpoint(endpoint *HNSEndpoint) (*HNSEndpoint, error) {
137	operation := "CreateRemoteEndpoint"
138	title := "HCSShim::HNSNetwork::" + operation
139	logrus.Debugf(title+" id=%s", network.Id)
140	endpoint.IsRemoteEndpoint = true
141	return network.CreateEndpoint(endpoint)
142}
143