Skip to content

Commit 8b89494

Browse files
author
Frank Zhang
committed
CLOUDSTACK-6278
Baremetal Advanced Networking support
1 parent d315a5e commit 8b89494

13 files changed

Lines changed: 182 additions & 92 deletions

File tree

plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,13 @@
2828
>
2929

3030
<bean id="BaremetalManager" class="com.cloud.baremetal.manager.BaremetalManagerImpl" />
31-
<bean id="BaremetalVlanManager" class="com.cloud.baremetal.manager.BaremetalVlanManagerImpl" />
31+
<bean id="BaremetalVlanManager" class="com.cloud.baremetal.manager.BaremetalVlanManagerImpl" >
32+
<property name="backends">
33+
<map>
34+
<entry key="Force10" value-ref="Force10BaremetalSwitchBackend"/>
35+
</map>
36+
</property>
37+
</bean>
3238
<bean id="Force10BaremetalSwitchBackend" class="com.cloud.baremetal.networkservice.Force10BaremetalSwitchBackend" />
3339

3440
<bean id="BaremetalKickStartPxeService"

plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManager.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package com.cloud.baremetal.manager;
1919

2020
import com.cloud.baremetal.networkservice.BaremetalRctResponse;
21+
import com.cloud.baremetal.networkservice.BaremetalSwitchBackend;
2122
import com.cloud.deploy.DeployDestination;
2223
import com.cloud.network.Network;
2324
import com.cloud.utils.component.Manager;
@@ -36,4 +37,6 @@ public interface BaremetalVlanManager extends Manager, PluggableService {
3637
void prepareVlan(Network nw, DeployDestination destHost);
3738

3839
void releaseVlan(Network nw, VirtualMachineProfile vm);
40+
41+
void registerSwitchBackend(BaremetalSwitchBackend backend);
3942
}

plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManagerImpl.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
import java.net.MalformedURLException;
4848
import java.net.URL;
4949
import java.util.ArrayList;
50-
import java.util.HashMap;
5150
import java.util.List;
5251
import java.util.Map;
5352
import java.util.UUID;
@@ -69,13 +68,17 @@ public class BaremetalVlanManagerImpl extends ManagerBase implements BaremetalVl
6968
@Inject
7069
private AccountManager acntMgr;
7170

72-
private Map<String, BaremetalSwitchBackend> backends = new HashMap<>();
71+
private Map<String, BaremetalSwitchBackend> backends;
7372

7473
private class RackPair {
7574
BaremetalRct.Rack rack;
7675
BaremetalRct.HostEntry host;
7776
}
7877

78+
public void setBackends(Map<String, BaremetalSwitchBackend> backends) {
79+
this.backends = backends;
80+
}
81+
7982
@Override
8083
public BaremetalRctResponse addRct(AddBaremetalRctCmd cmd) {
8184
try {
@@ -161,6 +164,11 @@ public void releaseVlan(Network nw, VirtualMachineProfile vm) {
161164
backend.removePortFromVlan(struct);
162165
}
163166

167+
@Override
168+
public void registerSwitchBackend(BaremetalSwitchBackend backend) {
169+
backends.put(backend.getSwitchBackendType(), backend);
170+
}
171+
164172
private BaremetalSwitchBackend getSwitchBackend(String type) {
165173
BaremetalSwitchBackend backend = backends.get(type);
166174
if (backend == null) {

plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ public PingCommand getCurrentStatus(long id) {
391391
VMInstanceVO vm = vms.get(0);
392392
SecurityGroupHttpClient client = new SecurityGroupHttpClient();
393393
HashMap<String, Pair<Long, Long>> nwGrpStates = client.sync(vm.getInstanceName(), vm.getId(), vm.getPrivateIpAddress());
394-
return new PingRoutingWithNwGroupsCommand(getType(), id, getHostVmStateReport(), nwGrpStates);
394+
return new PingRoutingWithNwGroupsCommand(getType(), id, null, nwGrpStates);
395395
}
396396
} else {
397397
return new PingRoutingCommand(getType(), id, getHostVmStateReport());

plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -219,19 +219,19 @@ private boolean preparePxeInAdvancedZone(VirtualMachineProfile profile, NicProfi
219219
}
220220

221221
List<String> tuple = parseKickstartUrl(profile);
222-
Pair<Boolean, String> ret = SshHelper.sshExecute(mgmtNic.getIp4Address(), 3922, "root", getSystemVMKeyFile(), null,
223-
String.format("/usr/bin/prepare_pxe.sh %s %s %s %s %s", tuple.get(1), tuple.get(2), profile.getTemplate().getUuid(),
224-
String.format("01-%s", nic.getMacAddress().replaceAll(":", "-")), tuple.get(0))
225-
);
222+
String cmd = String.format("/usr/bin/prepare_pxe.sh %s %s %s %s %s %s", tuple.get(1), tuple.get(2), profile.getTemplate().getUuid(),
223+
String.format("01-%s", nic.getMacAddress().replaceAll(":", "-")).toLowerCase(), tuple.get(0), nic.getMacAddress().toLowerCase());
224+
s_logger.debug(String.format("prepare pxe on virtual router[ip:%s], cmd: %s", mgmtNic.getIp4Address(), cmd));
225+
Pair<Boolean, String> ret = SshHelper.sshExecute(mgmtNic.getIp4Address(), 3922, "root", getSystemVMKeyFile(), null, cmd);
226226
if (!ret.first()) {
227227
throw new CloudRuntimeException(String.format("failed preparing PXE in virtual router[id:%s], because %s", vr.getId(), ret.second()));
228228
}
229229

230230
//String internalServerIp = _configDao.getValue(Config.BaremetalInternalStorageServer.key());
231231
String internalServerIp = "10.223.110.231";
232-
ret = SshHelper.sshExecute(mgmtNic.getIp4Address(), 3922, "root", getSystemVMKeyFile(), null,
233-
String.format("/usr/bin/baremetal_snat.sh %s %s", mgmtNic.getIp4Address(), internalServerIp)
234-
);
232+
cmd = String.format("/usr/bin/baremetal_snat.sh %s %s %s", mgmtNic.getIp4Address(), internalServerIp, mgmtNic.getGateway());
233+
s_logger.debug(String.format("prepare SNAT on virtual router[ip:%s], cmd: %s", mgmtNic.getIp4Address(), cmd));
234+
ret = SshHelper.sshExecute(mgmtNic.getIp4Address(), 3922, "root", getSystemVMKeyFile(), null, cmd);
235235
if (!ret.first()) {
236236
throw new CloudRuntimeException(String.format("failed preparing PXE in virtual router[id:%s], because %s", vr.getId(), ret.second()));
237237
}

plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.cloud.baremetal.database.BaremetalPxeVO;
2222
import com.cloud.baremetal.manager.BaremetalVlanManager;
2323
import com.cloud.dc.DataCenter;
24+
import com.cloud.dc.DataCenterVO;
2425
import com.cloud.dc.Pod;
2526
import com.cloud.dc.dao.DataCenterDao;
2627
import com.cloud.deploy.DeployDestination;
@@ -139,11 +140,9 @@ public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm
139140
}
140141
}
141142

142-
/*
143143
if (dest.getDataCenter().getNetworkType() == DataCenter.NetworkType.Advanced){
144144
prepareVlan(network, dest);
145145
}
146-
*/
147146

148147
return true;
149148
}
@@ -159,12 +158,10 @@ public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm
159158
return false;
160159
}
161160

162-
/*
163161
DataCenterVO dc = zoneDao.findById(vm.getVirtualMachine().getDataCenterId());
164162
if (dc.getNetworkType() == DataCenter.NetworkType.Advanced) {
165163
releaseVlan(network, vm);
166164
}
167-
*/
168165
return true;
169166
}
170167

plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/Force10BaremetalSwitchBackend.java

100644100755
Lines changed: 86 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,16 @@
3232
import org.springframework.http.HttpHeaders;
3333
import org.springframework.http.HttpMethod;
3434
import org.springframework.http.HttpStatus;
35+
import org.springframework.http.MediaType;
3536
import org.springframework.http.ResponseEntity;
37+
import org.springframework.http.client.ClientHttpResponse;
38+
import org.springframework.web.client.ResponseErrorHandler;
3639
import org.springframework.web.client.RestTemplate;
3740
import org.springframework.web.util.UriComponentsBuilder;
3841

42+
import java.io.IOException;
3943
import java.util.ArrayList;
44+
import java.util.Arrays;
4045
import 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

scripts/network/ping/baremetal_snat.sh

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,34 @@ set +u
2121

2222
mgmt_nic_ip=$1
2323
internal_server_ip=$2
24+
gateway_ip=$3
2425

2526
ip route | grep "$internal_server_ip" > /dev/null
2627

2728
if [ $? -ne 0 ]; then
28-
ip route add $internal_server_ip via $mgmt_nic_ip
29+
ip route add $internal_server_ip via $gateway_ip
2930
fi
3031

3132
iptables-save | grep -- "-A POSTROUTING -d $internal_server_ip" > /dev/null
3233

3334
if [ $? -ne 0 ]; then
3435
iptables -t nat -A POSTROUTING -d $internal_server_ip -j SNAT --to-source $mgmt_nic_ip
3536
fi
37+
38+
39+
iptables-save | grep -- "-A INPUT -i eth0 -p udp -m udp --dport 69 -j ACCEPT" > /dev/null
40+
if [ $? -ne 0 ]; then
41+
iptables -I INPUT -i eth0 -p udp -m udp --dport 69 -j ACCEPT
42+
fi
43+
44+
iptables-save | grep -- "-A FORWARD -i eth1 -o eth0 -j ACCEPT" > /dev/null
45+
if [ $? -ne 0 ]; then
46+
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
47+
fi
48+
49+
rule="-A FORWARD -d $internal_server_ip/32 -i eth0 -o eth1 -j ACCEPT"
50+
iptables-save | grep -- "$rule" > /dev/null
51+
if [ $? -ne 0 ]; then
52+
iptables -I FORWARD -d $internal_server_ip/32 -i eth0 -o eth1 -j ACCEPT
53+
fi
54+

0 commit comments

Comments
 (0)