Skip to content

Commit 93917e5

Browse files
committed
Restore CNS state and set SNAT rule.
Fixed bug in Makefile
1 parent e9bafb6 commit 93917e5

File tree

3 files changed

+110
-33
lines changed

3 files changed

+110
-33
lines changed

Makefile

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ CNIFILES = \
2929
CNSFILES = \
3030
$(wildcard cns/*.go) \
3131
$(wildcard cns/common/*.go) \
32-
$(wildcard cni/dockerclient/*.go) \
33-
$(wildcard cni/imdsclient/*.go) \
34-
$(wildcard cni/ipamclient/*.go) \
35-
$(wildcard cni/restserver/*.go) \
36-
$(wildcard cni/routes/*.go) \
37-
$(wildcard cni/service/*.go) \
32+
$(wildcard cns/dockerclient/*.go) \
33+
$(wildcard cns/imdsclient/*.go) \
34+
$(wildcard cns/ipamclient/*.go) \
35+
$(wildcard cns/restserver/*.go) \
36+
$(wildcard cns/routes/*.go) \
37+
$(wildcard cns/service/*.go) \
3838
$(COREFILES) \
3939
$(CNMFILES)
4040

cns/dockerclient/dockerclient.go

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import (
88
"encoding/json"
99
"fmt"
1010
"net/http"
11-
"os/exec"
1211

12+
"github.com/Azure/azure-container-networking/cns/common"
1313
"github.com/Azure/azure-container-networking/cns/imdsclient"
1414
"github.com/Azure/azure-container-networking/log"
1515
)
@@ -27,16 +27,6 @@ type DockerClient struct {
2727
imdsClient *imdsclient.ImdsClient
2828
}
2929

30-
func executeShellCommand(command string) error {
31-
log.Debugf("[Azure-CNS] %s", command)
32-
cmd := exec.Command("sh", "-c", command)
33-
err := cmd.Start()
34-
if err != nil {
35-
return err
36-
}
37-
return cmd.Wait()
38-
}
39-
4030
// NewDockerClient create a new docker client.
4131
func NewDockerClient(url string) (*DockerClient, error) {
4232
return &DockerClient{
@@ -81,18 +71,13 @@ func (dockerClient *DockerClient) NetworkExists(networkName string) error {
8171
}
8272

8373
// CreateNetwork creates a network using docker network create.
84-
func (dockerClient *DockerClient) CreateNetwork(networkName string, options map[string]interface{}) error {
74+
func (dockerClient *DockerClient) CreateNetwork(networkName string, nicInfo *imdsclient.InterfaceInfo, options map[string]interface{}) error {
8575
log.Printf("[Azure CNS] CreateNetwork")
8676

8777
enableSnat := true
8878

89-
primaryNic, err := dockerClient.imdsClient.GetPrimaryInterfaceInfoFromHost()
90-
if err != nil {
91-
return err
92-
}
93-
9479
config := &Config{
95-
Subnet: primaryNic.Subnet,
80+
Subnet: nicInfo.Subnet,
9681
}
9782

9883
configs := make([]Config, 1)
@@ -123,7 +108,7 @@ func (dockerClient *DockerClient) CreateNetwork(networkName string, options map[
123108
log.Printf("[Azure CNS] Going to create network with config: %+v", netConfig)
124109

125110
netConfigJSON := new(bytes.Buffer)
126-
err = json.NewEncoder(netConfigJSON).Encode(netConfig)
111+
err := json.NewEncoder(netConfigJSON).Encode(netConfig)
127112
if err != nil {
128113
return err
129114
}
@@ -150,12 +135,9 @@ func (dockerClient *DockerClient) CreateNetwork(networkName string, options map[
150135
}
151136

152137
if enableSnat {
153-
cmd := fmt.Sprintf("iptables -t nat -A POSTROUTING -m iprange ! --dst-range 168.63.129.16 -m addrtype ! --dst-type local ! -d %v -j MASQUERADE",
154-
primaryNic.Subnet)
155-
err = executeShellCommand(cmd)
138+
err = common.SetOutboundSNAT(nicInfo.Subnet)
156139
if err != nil {
157-
log.Printf("SNAT Iptable rule was not set")
158-
return err
140+
log.Printf("[Azure CNS] Error setting up SNAT outbound rule %v", err)
159141
}
160142
}
161143

@@ -186,7 +168,11 @@ func (dockerClient *DockerClient) DeleteNetwork(networkName string) error {
186168

187169
cmd := fmt.Sprintf("iptables -t nat -D POSTROUTING -m iprange ! --dst-range 168.63.129.16 -m addrtype ! --dst-type local ! -d %v -j MASQUERADE",
188170
primaryNic.Subnet)
189-
executeShellCommand(cmd)
171+
err = common.ExecuteShellCommand(cmd)
172+
if err != nil {
173+
log.Printf("[Azure CNS] Error Removing Outbound SNAT rule %v", err)
174+
}
175+
190176
return nil
191177
}
192178

cns/restserver/restserver.go

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/Azure/azure-container-networking/cns/ipamclient"
1717
"github.com/Azure/azure-container-networking/cns/routes"
1818
"github.com/Azure/azure-container-networking/log"
19+
"github.com/Azure/azure-container-networking/platform"
1920
"github.com/Azure/azure-container-networking/store"
2021
)
2122

@@ -32,17 +33,24 @@ type httpRestService struct {
3233
ipamClient *ipamclient.IpamClient
3334
routingTable *routes.RoutingTable
3435
store store.KeyValueStore
35-
state httpRestServiceState
36+
state *httpRestServiceState
3637
}
3738

3839
// httpRestServiceState contains the state we would like to persist.
3940
type httpRestServiceState struct {
4041
Location string
4142
NetworkType string
4243
Initialized bool
44+
Networks map[string]*networkInfo
4345
TimeStamp time.Time
4446
}
4547

48+
type networkInfo struct {
49+
NetworkName string
50+
NicInfo *imdsclient.InterfaceInfo
51+
Options map[string]interface{}
52+
}
53+
4654
// HTTPService describes the min API interface that every service should have.
4755
type HTTPService interface {
4856
common.ServiceAPI
@@ -67,14 +75,19 @@ func NewHTTPRestService(config *common.ServiceConfig) (HTTPService, error) {
6775
return nil, err
6876
}
6977

78+
serviceState := &httpRestServiceState{}
79+
serviceState.Networks = make(map[string]*networkInfo)
80+
7081
return &httpRestService{
7182
Service: service,
7283
store: service.Service.Store,
7384
dockerClient: dc,
7485
imdsClient: imdsClient,
7586
ipamClient: ic,
7687
routingTable: routingTable,
88+
state: serviceState,
7789
}, nil
90+
7891
}
7992

8093
// Start starts the CNS listener.
@@ -86,6 +99,18 @@ func (service *httpRestService) Start(config *common.ServiceConfig) error {
8699
return err
87100
}
88101

102+
err = service.restoreState()
103+
if err != nil {
104+
log.Printf("[Azure CNS] Failed to restore state, err:%v.", err)
105+
return err
106+
}
107+
108+
err = service.restoreNetworkState()
109+
if err != nil {
110+
log.Printf("[Azure CNS] Failed to restore state, err:%v.", err)
111+
return err
112+
}
113+
89114
// Add handlers.
90115
listener := service.Listener
91116
// default handlers
@@ -186,7 +211,14 @@ func (service *httpRestService) createNetwork(w http.ResponseWriter, r *http.Req
186211
log.Printf("[Azure CNS] Unable to get routing table from node, %+v.", err.Error())
187212
}
188213

189-
err = dc.CreateNetwork(req.NetworkName, req.Options)
214+
nicInfo, err := service.imdsClient.GetPrimaryInterfaceInfoFromHost()
215+
if err != nil {
216+
returnMessage = fmt.Sprintf("[Azure CNS] Error. CreateNetwork failed %v.", err.Error())
217+
returnCode = UnexpectedError
218+
break
219+
}
220+
221+
err = dc.CreateNetwork(req.NetworkName, nicInfo, req.Options)
190222
if err != nil {
191223
returnMessage = fmt.Sprintf("[Azure CNS] Error. CreateNetwork failed %v.", err.Error())
192224
returnCode = UnexpectedError
@@ -197,6 +229,14 @@ func (service *httpRestService) createNetwork(w http.ResponseWriter, r *http.Req
197229
log.Printf("[Azure CNS] Unable to restore routing table on node, %+v.", err.Error())
198230
}
199231

232+
networkInfo := &networkInfo{
233+
NetworkName: req.NetworkName,
234+
NicInfo: nicInfo,
235+
Options: req.Options,
236+
}
237+
238+
service.state.Networks[req.NetworkName] = networkInfo
239+
200240
case "StandAlone":
201241
returnMessage = fmt.Sprintf("[Azure CNS] Error. Underlay network is not supported in StandAlone environment. %v.", err.Error())
202242
returnCode = UnsupportedEnvironment
@@ -228,6 +268,10 @@ func (service *httpRestService) createNetwork(w http.ResponseWriter, r *http.Req
228268

229269
err = service.Listener.Encode(w, &resp)
230270

271+
if returnCode == 0 {
272+
service.saveState()
273+
}
274+
231275
log.Response(service.Name, resp, err)
232276
}
233277

@@ -279,6 +323,11 @@ func (service *httpRestService) deleteNetwork(w http.ResponseWriter, r *http.Req
279323

280324
err = service.Listener.Encode(w, &resp)
281325

326+
if returnCode == 0 {
327+
delete(service.state.Networks, req.NetworkName)
328+
service.saveState()
329+
}
330+
282331
log.Response(service.Name, resp, err)
283332
}
284333

@@ -723,3 +772,45 @@ func (service *httpRestService) restoreState() error {
723772
log.Printf("[Azure CNS] Restored state, %+v\n", service.state)
724773
return nil
725774
}
775+
776+
// restoreNetworkState restores Network state that existed before reboot.
777+
func (service *httpRestService) restoreNetworkState() error {
778+
log.Printf("[Azure CNS] Enter Restoring Network State")
779+
780+
rebooted := false
781+
782+
modTime, err := service.store.GetModificationTime()
783+
if err == nil {
784+
log.Printf("[Azure CNS] Store timestamp is %v.", modTime)
785+
786+
rebootTime, err := platform.GetLastRebootTime()
787+
if err == nil && rebootTime.After(modTime) {
788+
log.Printf("[Azure CNS] reboot time %v mod time %v", rebootTime, modTime)
789+
rebooted = true
790+
}
791+
}
792+
793+
if rebooted {
794+
for _, nwInfo := range service.state.Networks {
795+
enableSnat := true
796+
797+
log.Printf("[Azure CNS] Restore nwinfo %v", nwInfo)
798+
799+
if nwInfo.Options != nil {
800+
if _, ok := nwInfo.Options[dockerclient.OptDisableSnat]; ok {
801+
enableSnat = false
802+
}
803+
}
804+
805+
if enableSnat {
806+
err := common.SetOutboundSNAT(nwInfo.NicInfo.Subnet)
807+
if err != nil {
808+
log.Printf("[Azure CNS] Error setting up SNAT outbound rule %v", err)
809+
return err
810+
}
811+
}
812+
}
813+
}
814+
815+
return nil
816+
}

0 commit comments

Comments
 (0)