1package gsclient
2
3import (
4	"context"
5	"errors"
6	"net/http"
7	"path"
8)
9
10//ServerNetworkRelationList JSON struct of a list of relations between a server and networks
11type ServerNetworkRelationList struct {
12	//Array of relations between a server and networks
13	List []ServerNetworkRelationProperties `json:"network_relations"`
14}
15
16//ServerNetworkRelation JSON struct of a single relation between a server and a network
17type ServerNetworkRelation struct {
18	//Properties of a relation between a server and a network
19	Properties ServerNetworkRelationProperties `json:"network_relation"`
20}
21
22//ServerNetworkRelationProperties JSON struct of properties of a relation between a server and a network
23type ServerNetworkRelationProperties struct {
24	//Defines information about MAC spoofing protection (filters layer2 and ARP traffic based on MAC source).
25	//It can only be (de-)activated on a private network - the public network always has l2security enabled.
26	//It will be true if the network is public, and false if the network is private.
27	L2security bool `json:"l2security"`
28
29	//The UUID of the Server.
30	ServerUUID string `json:"server_uuid"`
31
32	//Defines the date and time the object was initially created.
33	CreateTime GSTime `json:"create_time"`
34
35	//True if the network is public. If private it will be false.
36	//Each private network is a secure and fully transparent 2-Layer network between servers.
37	//There is no limit on how many servers can be connected to the same private network.
38	PublicNet bool `json:"public_net"`
39
40	//The UUID of firewall template.
41	FirewallTemplateUUID string `json:"firewall_template_uuid"`
42
43	//The human-readable name of the object. It supports the full UTF-8 charset, with a maximum of 64 characters.
44	ObjectName string `json:"object_name"`
45
46	//network_mac defines the MAC address of the network interface.
47	Mac string `json:"mac"`
48
49	//Defines if this object is the bootdevice. Storages, Networks and ISO-Images can have a bootdevice configured,
50	//but only one bootdevice per Storage, Network or ISO-Image.
51	//The boot order is as follows => Network > ISO-Image > Storage.
52	BootDevice bool `json:"bootdevice"`
53
54	//PartnerUUID
55	PartnerUUID string `json:"partner_uuid"`
56
57	//Defines the ordering of the network interfaces. Lower numbers have lower PCI-IDs.
58	Ordering int `json:"ordering"`
59
60	//Firewall that is used to this server network relation
61	Firewall FirewallRules `json:"firewall"`
62
63	//(one of network, network_high, network_insane)
64	NetworkType string `json:"network_type"`
65
66	//The UUID of the network you're requesting.
67	NetworkUUID string `json:"network_uuid"`
68
69	//The UUID of an object is always unique, and refers to a specific object.
70	ObjectUUID string `json:"object_uuid"`
71
72	//Defines information about IP prefix spoof protection (it allows source traffic only from the IPv4/IPv4 network prefixes).
73	//If empty, it allow no IPv4/IPv6 source traffic. If set to null, l3security is disabled (default).
74	L3security []string `json:"l3security"`
75}
76
77//ServerNetworkRelationCreateRequest JSON struct of a request for creating a relation between a server and a network
78type ServerNetworkRelationCreateRequest struct {
79	//The uuid of network you wish to add. Only 7 private networks are allowed to be attached to a server
80	ObjectUUID string `json:"object_uuid"`
81
82	//The ordering of the network interfaces. Lower numbers have lower PCI-IDs. Can be empty.
83	Ordering int `json:"ordering,omitempty"`
84
85	//Whether the server boots from this network or not. Can be empty.
86	BootDevice bool `json:"bootdevice,omitempty"`
87
88	//Defines information about IP prefix spoof protection (it allows source traffic only from the IPv4/IPv4 network prefixes).
89	//If empty, it allow no IPv4/IPv6 source traffic. If set to null, l3security is disabled (default).
90	//Can be empty
91	L3security []string `json:"l3security,omitempty"`
92
93	//All rules of Firewall. Can be empty
94	Firewall *FirewallRules `json:"firewall,omitempty"`
95
96	//Instead of setting firewall rules manually, you can use a firewall template by setting UUID of the firewall template.
97	//Can be empty.
98	FirewallTemplateUUID string `json:"firewall_template_uuid,omitempty"`
99}
100
101//ServerNetworkRelationUpdateRequest JSON struct of a request for updating a relation between a server and a network
102type ServerNetworkRelationUpdateRequest struct {
103	//The ordering of the network interfaces. Lower numbers have lower PCI-IDs. Optional.
104	Ordering int `json:"ordering,omitempty"`
105
106	//The ordering of the network interfaces. Lower numbers have lower PCI-IDs. Optional.
107	BootDevice bool `json:"bootdevice,omitempty"`
108
109	//Defines information about IP prefix spoof protection (it allows source traffic only from the IPv4/IPv4 network prefixes).
110	//If empty, it allow no IPv4/IPv6 source traffic. If set to null, l3security is disabled (default).
111	//Can be empty
112	L3security []string `json:"l3security,omitempty"`
113
114	//All rules of Firewall. Optional.
115	Firewall *FirewallRules `json:"firewall,omitempty"`
116
117	//Instead of setting firewall rules manually, you can use a firewall template by setting UUID of the firewall template.
118	//Optional.
119	FirewallTemplateUUID string `json:"firewall_template_uuid,omitempty"`
120}
121
122//GetServerNetworkList gets a list of a specific server's networks
123//
124//See: https://gridscale.io/en//api-documentation/index.html#operation/getServerLinkedNetworks
125func (c *Client) GetServerNetworkList(ctx context.Context, id string) ([]ServerNetworkRelationProperties, error) {
126	if !isValidUUID(id) {
127		return nil, errors.New("'id' is invalid")
128	}
129	r := gsRequest{
130		uri:                 path.Join(apiServerBase, id, "networks"),
131		method:              http.MethodGet,
132		skipCheckingRequest: true,
133	}
134	var response ServerNetworkRelationList
135	err := r.execute(ctx, *c, &response)
136	return response.List, err
137}
138
139//GetServerNetwork gets a network of a specific server
140//
141//See: https://gridscale.io/en//api-documentation/index.html#operation/getServerLinkedNetwork
142func (c *Client) GetServerNetwork(ctx context.Context, serverID, networkID string) (ServerNetworkRelationProperties, error) {
143	if !isValidUUID(serverID) || !isValidUUID(networkID) {
144		return ServerNetworkRelationProperties{}, errors.New("'serverID' or 'networksID' is invalid")
145	}
146	r := gsRequest{
147		uri:                 path.Join(apiServerBase, serverID, "networks", networkID),
148		method:              http.MethodGet,
149		skipCheckingRequest: true,
150	}
151	var response ServerNetworkRelation
152	err := r.execute(ctx, *c, &response)
153	return response.Properties, err
154}
155
156//UpdateServerNetwork updates a link between a network and a server
157//
158//See: https://gridscale.io/en//api-documentation/index.html#operation/updateServerLinkedNetwork
159func (c *Client) UpdateServerNetwork(ctx context.Context, serverID, networkID string, body ServerNetworkRelationUpdateRequest) error {
160	if !isValidUUID(serverID) || !isValidUUID(networkID) {
161		return errors.New("'serverID' or 'networksID' is invalid")
162	}
163	r := gsRequest{
164		uri:    path.Join(apiServerBase, serverID, "networks", networkID),
165		method: http.MethodPatch,
166		body:   body,
167	}
168	return r.execute(ctx, *c, nil)
169}
170
171//CreateServerNetwork creates a link between a network and a storage
172//
173//See: https://gridscale.io/en//api-documentation/index.html#operation/linkNetworkToServer
174func (c *Client) CreateServerNetwork(ctx context.Context, id string, body ServerNetworkRelationCreateRequest) error {
175	if !isValidUUID(id) || !isValidUUID(body.ObjectUUID) {
176		return errors.New("'serverID' or 'network_id' is invalid")
177	}
178	r := gsRequest{
179		uri:    path.Join(apiServerBase, id, "networks"),
180		method: http.MethodPost,
181		body:   body,
182	}
183	return r.execute(ctx, *c, nil)
184}
185
186//DeleteServerNetwork deletes a link between a network and a server
187//
188//See: https://gridscale.io/en//api-documentation/index.html#operation/unlinkNetworkFromServer
189func (c *Client) DeleteServerNetwork(ctx context.Context, serverID, networkID string) error {
190	if !isValidUUID(serverID) || !isValidUUID(networkID) {
191		return errors.New("'serverID' or 'networkID' is invalid")
192	}
193	r := gsRequest{
194		uri:    path.Join(apiServerBase, serverID, "networks", networkID),
195		method: http.MethodDelete,
196	}
197	return r.execute(ctx, *c, nil)
198}
199
200//LinkNetwork attaches a network to a server
201func (c *Client) LinkNetwork(ctx context.Context, serverID, networkID, firewallTemplate string, bootdevice bool, order int,
202	l3security []string, firewall *FirewallRules) error {
203	body := ServerNetworkRelationCreateRequest{
204		ObjectUUID:           networkID,
205		Ordering:             order,
206		BootDevice:           bootdevice,
207		L3security:           l3security,
208		FirewallTemplateUUID: firewallTemplate,
209		Firewall:             firewall,
210	}
211	return c.CreateServerNetwork(ctx, serverID, body)
212}
213
214//UnlinkNetwork removes the link between a network and a server
215func (c *Client) UnlinkNetwork(ctx context.Context, serverID string, networkID string) error {
216	return c.DeleteServerNetwork(ctx, serverID, networkID)
217}
218