3232import org .springframework .http .HttpHeaders ;
3333import org .springframework .http .HttpMethod ;
3434import org .springframework .http .HttpStatus ;
35+ import org .springframework .http .MediaType ;
3536import org .springframework .http .ResponseEntity ;
37+ import org .springframework .http .client .ClientHttpResponse ;
38+ import org .springframework .web .client .ResponseErrorHandler ;
3639import org .springframework .web .client .RestTemplate ;
3740import org .springframework .web .util .UriComponentsBuilder ;
3841
42+ import java .io .IOException ;
3943import java .util .ArrayList ;
44+ import java .util .Arrays ;
4045import java .util .List ;
4146
4247/**
@@ -46,17 +51,38 @@ public class Force10BaremetalSwitchBackend implements BaremetalSwitchBackend {
4651 private Logger logger = Logger .getLogger (Force10BaremetalSwitchBackend .class );
4752 public static final String TYPE = "Force10" ;
4853
54+ private static List <HttpStatus > successHttpStatusCode = new ArrayList <>();
55+ {
56+ successHttpStatusCode .add (HttpStatus .OK );
57+ successHttpStatusCode .add (HttpStatus .ACCEPTED );
58+ successHttpStatusCode .add (HttpStatus .CREATED );
59+ successHttpStatusCode .add (HttpStatus .NO_CONTENT );
60+ successHttpStatusCode .add (HttpStatus .PARTIAL_CONTENT );
61+ successHttpStatusCode .add (HttpStatus .RESET_CONTENT );
62+ successHttpStatusCode .add (HttpStatus .ALREADY_REPORTED );
63+ }
64+
4965 RestTemplate rest = new RestTemplate ();
66+ {
67+ // fake error handler, we handle error in business logic code
68+ rest .setErrorHandler (new ResponseErrorHandler () {
69+ @ Override
70+ public boolean hasError (ClientHttpResponse clientHttpResponse ) throws IOException {
71+ return false ;
72+ }
5073
51- private String buildLink (String switchIp , Integer vlan ) {
74+ @ Override
75+ public void handleError (ClientHttpResponse clientHttpResponse ) throws IOException {
76+ }
77+ });
78+ }
79+
80+ private String buildLink (String switchIp , String path ) {
5281 UriComponentsBuilder builder = UriComponentsBuilder .newInstance ();
5382 builder .scheme ("http" );
5483 builder .host (switchIp );
5584 builder .port (8008 );
56- builder .path ("/api/running/ftos/interface/vlan" );
57- if (vlan != null ) {
58- builder .path (vlan .toString ());
59- }
85+ builder .path (path );
6086 return builder .build ().toUriString ();
6187 }
6288
@@ -67,29 +93,36 @@ public String getSwitchBackendType() {
6793
6894 @ Override
6995 public void prepareVlan (BaremetalVlanStruct struct ) {
70- String link = buildLink (struct .getSwitchIp (), struct .getVlan ());
96+ String link = buildLink (struct .getSwitchIp (), String . format ( "/api/running/ftos/interface/vlan/%s" , struct .getVlan () ));
7197 HttpHeaders headers = createBasicAuthenticationHeader (struct );
7298 HttpEntity <String > request = new HttpEntity <>(headers );
7399 ResponseEntity rsp = rest .exchange (link , HttpMethod .GET , request , String .class );
100+ logger .debug (String .format ("http get: %s" , link ));
74101
75102 if (rsp .getStatusCode () == HttpStatus .NOT_FOUND ) {
76103 PortInfo port = new PortInfo (struct );
77- XmlObject xml = new XmlObject ("vlan" ).putElement ("vlan-id" , String .valueOf (struct .getVlan ())).putElement ("tagged" ,
78- new XmlObject (port .interfaceType ).putElement ("name" , port .port )
79- ).putElement ("shutdown" , "false" );
80- request = new HttpEntity <>(xml .toString (), headers );
81- link = buildLink (struct .getSwitchIp (), null );
82- rsp = rest .exchange (link , HttpMethod .GET , request , String .class );
83- if (rsp .getStatusCode () != HttpStatus .OK ) {
104+ XmlObject xml = new XmlObject ("vlan" ).putElement ("vlan-id" ,
105+ new XmlObject ("vlan-id" ).setText (String .valueOf (struct .getVlan ()))).putElement ("untagged" ,
106+ new XmlObject ("untagged" ).putElement (port .interfaceType , new XmlObject (port .interfaceType )
107+ .putElement ("name" , new XmlObject ("name" ).setText (port .port )))
108+ ).putElement ("shutdown" , new XmlObject ("shutdown" ).setText ("false" ));
109+ request = new HttpEntity <>(xml .dump (), headers );
110+ link = buildLink (struct .getSwitchIp (), String .format ("/api/running/ftos/interface/" ));
111+ logger .debug (String .format ("http get: %s, body: %s" , link , request ));
112+ rsp = rest .exchange (link , HttpMethod .POST , request , String .class );
113+ if (!successHttpStatusCode .contains (rsp .getStatusCode ())) {
84114 throw new CloudRuntimeException (String .format ("unable to create vlan[%s] on force10 switch[ip:%s]. HTTP status code:%s, body dump:%s" ,
85- struct .getVlan (), rsp .getStatusCode (), struct .getSwitchIp (), rsp .getBody ()));
115+ struct .getVlan (), struct .getSwitchIp (),rsp .getStatusCode (), rsp .getBody ()));
116+ } else {
117+ logger .debug (String .format ("successfully programmed vlan[%s] on Force10[ip:%s, port:%s]. http response[status code:%s, body:%s]" ,
118+ struct .getVlan (), struct .getSwitchIp (), struct .getPort (), rsp .getStatusCode (), rsp .getBody ()));
86119 }
87- } else if (rsp .getStatusCode () == HttpStatus . OK ) {
120+ } else if (successHttpStatusCode . contains ( rsp .getStatusCode ()) ) {
88121 PortInfo port = new PortInfo (struct );
89122 XmlObject xml = XmlObjectParser .parseFromString ((String )rsp .getBody ());
90- List <XmlObject > ports = xml .getAsList ("tagged .tengigabitethernet" );
91- ports .addAll (xml .<XmlObject >getAsList ("tagged .gigabitethernet" ));
92- ports .addAll (xml .<XmlObject >getAsList ("tagged .fortyGigE" ));
123+ List <XmlObject > ports = xml .getAsList ("untagged .tengigabitethernet" );
124+ ports .addAll (xml .<XmlObject >getAsList ("untagged .gigabitethernet" ));
125+ ports .addAll (xml .<XmlObject >getAsList ("untagged .fortyGigE" ));
93126 for (XmlObject pxml : ports ) {
94127 XmlObject name = pxml .get ("name" );
95128 if (port .port .equals (name .getText ())) {
@@ -98,14 +131,26 @@ public void prepareVlan(BaremetalVlanStruct struct) {
98131 }
99132 }
100133
101- XmlObject tag = xml .get ("tagged" );
102- tag .putElement (port .interfaceType , new XmlObject ("name" ).setText (port .port ));
103- request = new HttpEntity <>(xml .toString (), headers );
104- link = buildLink (struct .getSwitchIp (), struct .getVlan ());
134+ xml .removeElement ("mtu" );
135+ xml .setText (null );
136+ XmlObject tag = xml .get ("untagged" );
137+ if (tag == null ) {
138+ tag = new XmlObject ("untagged" );
139+ xml .putElement ("untagged" , tag );
140+ }
141+
142+ tag .putElement (port .interfaceType , new XmlObject (port .interfaceType )
143+ .putElement ("name" , new XmlObject ("name" ).setText (port .port )));
144+ request = new HttpEntity <>(xml .dump (), headers );
145+ link = buildLink (struct .getSwitchIp (), String .format ("/api/running/ftos/interface/vlan/%s" , struct .getVlan ()));
146+ logger .debug (String .format ("http get: %s, body: %s" , link , request ));
105147 rsp = rest .exchange (link , HttpMethod .PUT , request , String .class );
106- if (rsp .getStatusCode () != HttpStatus . NO_CONTENT ) {
148+ if (! successHttpStatusCode . contains ( rsp .getStatusCode ()) ) {
107149 throw new CloudRuntimeException (String .format ("failed to program vlan[%s] for port[%s] on force10[ip:%s]. http status:%s, body dump:%s" ,
108150 struct .getVlan (), struct .getPort (), struct .getSwitchIp (), rsp .getStatusCode (), rsp .getBody ()));
151+ } else {
152+ logger .debug (String .format ("successfully join port[%s] into vlan[%s] on Force10[ip:%s]. http response[status code:%s, body:%s]" ,
153+ struct .getPort (), struct .getVlan (), struct .getSwitchIp (), rsp .getStatusCode (), rsp .getBody ()));
109154 }
110155 } else {
111156 throw new CloudRuntimeException (String .format ("force10[ip:%s] returns unexpected error[%s] when http getting %s, body dump:%s" ,
@@ -115,18 +160,19 @@ public void prepareVlan(BaremetalVlanStruct struct) {
115160
116161 @ Override
117162 public void removePortFromVlan (BaremetalVlanStruct struct ) {
118- String link = buildLink (struct .getSwitchIp (), struct .getVlan ());
163+ String link = buildLink (struct .getSwitchIp (), String . format ( "/api/running/ftos/interface/vlan/%s" , struct .getVlan () ));
119164 HttpHeaders headers = createBasicAuthenticationHeader (struct );
120165 HttpEntity <String > request = new HttpEntity <>(headers );
166+ logger .debug (String .format ("http get: %s, body: %s" , link , request ));
121167 ResponseEntity rsp = rest .exchange (link , HttpMethod .GET , request , String .class );
122168 if (rsp .getStatusCode () == HttpStatus .NOT_FOUND ) {
123169 logger .debug (String .format ("vlan[%s] has been deleted on force10[ip:%s], no need to remove the port[%s] anymore" , struct .getVlan (), struct .getSwitchIp (), struct .getPort ()));
124170 } else if (rsp .getStatusCode () == HttpStatus .OK ) {
125171 PortInfo port = new PortInfo (struct );
126172 XmlObject xml = XmlObjectParser .parseFromString ((String )rsp .getBody ());
127- List <XmlObject > ports = xml .getAsList ("tagged .tengigabitethernet" );
128- ports .addAll (xml .<XmlObject >getAsList ("tagged .gigabitethernet" ));
129- ports .addAll (xml .<XmlObject >getAsList ("tagged .fortyGigE" ));
173+ List <XmlObject > ports = xml .getAsList ("untagged .tengigabitethernet" );
174+ ports .addAll (xml .<XmlObject >getAsList ("untagged .gigabitethernet" ));
175+ ports .addAll (xml .<XmlObject >getAsList ("untagged .fortyGigE" ));
130176 List <XmlObject > newPorts = new ArrayList <>();
131177 boolean needRemove = false ;
132178 for (XmlObject pxml : ports ) {
@@ -143,11 +189,19 @@ public void removePortFromVlan(BaremetalVlanStruct struct) {
143189 return ;
144190 }
145191
146- xml .putElement ("tagged" , newPorts );
192+ xml .setText (null );
193+ xml .removeElement ("mtu" );
194+ XmlObject tagged = xml .get ("untagged" );
195+ tagged .removeAllChildren ();
196+ for (XmlObject p : newPorts ) {
197+ tagged .putElement (p .getTag (), p );
198+ }
199+
147200
148- request = new HttpEntity <>(xml .toString (), headers );
201+ request = new HttpEntity <>(xml .dump (), headers );
202+ logger .debug (String .format ("http get: %s, body: %s" , link , request ));
149203 rsp = rest .exchange (link , HttpMethod .PUT , request , String .class );
150- if (rsp .getStatusCode () != HttpStatus . NO_CONTENT ) {
204+ if (! successHttpStatusCode . contains ( rsp .getStatusCode ()) ) {
151205 throw new CloudRuntimeException (String .format ("failed to program vlan[%s] for port[%s] on force10[ip:%s]. http status:%s, body dump:%s" ,
152206 struct .getVlan (), struct .getPort (), struct .getSwitchIp (), rsp .getStatusCode (), rsp .getBody ()));
153207 } else {
@@ -166,6 +220,8 @@ private HttpHeaders createBasicAuthenticationHeader(BaremetalVlanStruct struct)
166220 String base64Creds = new String (base64CredsBytes );
167221 HttpHeaders headers = new HttpHeaders ();
168222 headers .add ("Authorization" , "Basic " + base64Creds );
223+ headers .setAccept (Arrays .asList (MediaType .ALL ));
224+ headers .setContentType (MediaType .valueOf ("application/vnd.yang.data+xml" ));
169225 return headers ;
170226 }
171227
0 commit comments