diff --git a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml
old mode 100644
new mode 100755
index e1a21bc0597..ae28efad6db
--- a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml
+++ b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml
@@ -29,6 +29,7 @@
+
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalRct.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalRct.java
index 9ed7cf4caa5..96e78650743 100755
--- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalRct.java
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalRct.java
@@ -65,7 +65,7 @@ public class BaremetalRct {
public static class HostEntry {
private String uuid;
private String mac;
- private int port;
+ private String port;
public String getUuid() {
return uuid;
@@ -83,11 +83,11 @@ public class BaremetalRct {
this.mac = mac;
}
- public int getPort() {
+ public String getPort() {
return port;
}
- public void setPort(int port) {
+ public void setPort(String port) {
this.port = port;
}
}
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManager.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManager.java
index 13e61fa9533..16626682432 100755
--- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManager.java
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManager.java
@@ -18,8 +18,11 @@
package com.cloud.baremetal.manager;
import com.cloud.baremetal.networkservice.BaremetalRctResponse;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.network.Network;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.PluggableService;
+import com.cloud.vm.VirtualMachineProfile;
import org.apache.cloudstack.api.AddBaremetalRctCmd;
/**
@@ -29,4 +32,8 @@ public interface BaremetalVlanManager extends Manager, PluggableService {
public static final String BAREMETAL_SYSTEM_ACCOUNT_NAME = "baremetal-system-account";
BaremetalRctResponse addRct(AddBaremetalRctCmd cmd);
+
+ void prepareVlan(Network nw, DeployDestination destHost);
+
+ void releaseVlan(Network nw, VirtualMachineProfile vm);
}
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManagerImpl.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManagerImpl.java
index f307af4cca4..0334fb30815 100755
--- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManagerImpl.java
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManagerImpl.java
@@ -20,6 +20,13 @@ package com.cloud.baremetal.manager;
import com.cloud.baremetal.database.BaremetalRctDao;
import com.cloud.baremetal.database.BaremetalRctVO;
import com.cloud.baremetal.networkservice.BaremetalRctResponse;
+import com.cloud.baremetal.networkservice.BaremetalSwitchBackend;
+import com.cloud.baremetal.networkservice.BaremetalVlanStruct;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.network.Network;
+import com.cloud.network.Networks;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
@@ -29,6 +36,8 @@ import com.cloud.user.dao.UserDao;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.QueryBuilder;
import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.VirtualMachineProfile;
import com.google.gson.Gson;
import org.apache.cloudstack.api.AddBaremetalRctCmd;
import org.apache.cloudstack.api.command.admin.user.RegisterCmd;
@@ -38,7 +47,9 @@ import javax.inject.Inject;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
/**
@@ -50,12 +61,21 @@ public class BaremetalVlanManagerImpl extends ManagerBase implements BaremetalVl
@Inject
private BaremetalRctDao rctDao;
@Inject
+ private HostDao hostDao;
+ @Inject
private AccountDao acntDao;
@Inject
private UserDao userDao;
@Inject
private AccountManager acntMgr;
+ private Map backends = new HashMap<>();
+
+ private class RackPair {
+ BaremetalRct.Rack rack;
+ BaremetalRct.HostEntry host;
+ }
+
@Override
public BaremetalRctResponse addRct(AddBaremetalRctCmd cmd) {
try {
@@ -87,11 +107,95 @@ public class BaremetalVlanManagerImpl extends ManagerBase implements BaremetalVl
}
}
+ @Override
+ public void prepareVlan(Network nw, DeployDestination destHost) {
+ List vos = rctDao.listAll();
+ if (vos.isEmpty()) {
+ throw new CloudRuntimeException("no rack configuration found, please call addBaremetalRct to add one");
+ }
+
+ BaremetalRctVO vo = vos.get(0);
+ BaremetalRct rct = gson.fromJson(vo.getRct(), BaremetalRct.class);
+
+ RackPair rp = findRack(rct, destHost.getHost().getPrivateMacAddress());
+ if (rp == null) {
+ throw new CloudRuntimeException(String.format("cannot find any rack contains host[mac:%s], please double check your rack configuration file, update it and call addBaremetalRct again", destHost.getHost().getPrivateMacAddress()));
+ }
+
+ int vlan = Integer.parseInt(Networks.BroadcastDomainType.getValue(nw.getBroadcastUri()));
+ BaremetalSwitchBackend backend = getSwitchBackend(rp.rack.getL2Switch().getType());
+ BaremetalVlanStruct struct = new BaremetalVlanStruct();
+ struct.setHostMac(rp.host.getMac());
+ struct.setPort(rp.host.getPort());
+ struct.setSwitchIp(rp.rack.getL2Switch().getIp());
+ struct.setSwitchPassword(rp.rack.getL2Switch().getPassword());
+ struct.setSwitchType(rp.rack.getL2Switch().getType());
+ struct.setSwitchUsername(rp.rack.getL2Switch().getUsername());
+ struct.setVlan(vlan);
+ backend.prepareVlan(struct);
+ }
+
+ @Override
+ public void releaseVlan(Network nw, VirtualMachineProfile vm) {
+ List vos = rctDao.listAll();
+ if (vos.isEmpty()) {
+ throw new CloudRuntimeException("no rack configuration found, please call addBaremetalRct to add one");
+ }
+
+ BaremetalRctVO vo = vos.get(0);
+ BaremetalRct rct = gson.fromJson(vo.getRct(), BaremetalRct.class);
+ HostVO host = hostDao.findById(vm.getVirtualMachine().getHostId());
+ RackPair rp = findRack(rct, host.getPrivateMacAddress());
+ assert rp != null : String.format("where is my rack???");
+
+ int vlan = Integer.parseInt(Networks.BroadcastDomainType.getValue(nw.getBroadcastUri()));
+ BaremetalVlanStruct struct = new BaremetalVlanStruct();
+ struct.setHostMac(rp.host.getMac());
+ struct.setPort(rp.host.getPort());
+ struct.setSwitchIp(rp.rack.getL2Switch().getIp());
+ struct.setSwitchPassword(rp.rack.getL2Switch().getPassword());
+ struct.setSwitchType(rp.rack.getL2Switch().getType());
+ struct.setSwitchUsername(rp.rack.getL2Switch().getUsername());
+ struct.setVlan(vlan);
+ BaremetalSwitchBackend backend = getSwitchBackend(rp.rack.getL2Switch().getType());
+ backend.removePortFromVlan(struct);
+ }
+
+ private BaremetalSwitchBackend getSwitchBackend(String type) {
+ BaremetalSwitchBackend backend = backends.get(type);
+ if (backend == null) {
+ throw new CloudRuntimeException(String.format("cannot find switch backend[type:%s]", type));
+ }
+ return backend;
+ }
+
+ private RackPair findRack(BaremetalRct rct, String mac) {
+ for (BaremetalRct.Rack rack : rct.getRacks()) {
+ for (BaremetalRct.HostEntry host : rack.getHosts()) {
+ if (mac.equals(host.getMac())) {
+ RackPair p = new RackPair();
+ p.host = host;
+ p.rack = rack;
+ return p;
+ }
+ }
+ }
+ return null;
+ }
+
@Override
public String getName() {
return "Baremetal Vlan Manager";
}
+
+ @Override
+ public List> getCommands() {
+ List> cmds = new ArrayList>();
+ cmds.add(AddBaremetalRctCmd.class);
+ return cmds;
+ }
+
@Override
public boolean start() {
QueryBuilder acntq = QueryBuilder.create(AccountVO.class);
@@ -126,12 +230,4 @@ public class BaremetalVlanManagerImpl extends ManagerBase implements BaremetalVl
userDao.update(user.getId(), user);
return true;
}
-
-
- @Override
- public List> getCommands() {
- List> cmds = new ArrayList>();
- cmds.add(AddBaremetalRctCmd.class);
- return cmds;
- }
}
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java
index b314bdbef45..9b835bf47a5 100755
--- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java
@@ -19,8 +19,11 @@
package com.cloud.baremetal.networkservice;
import com.cloud.baremetal.database.BaremetalPxeVO;
+import com.cloud.baremetal.manager.BaremetalVlanManager;
import com.cloud.dc.DataCenter;
+import com.cloud.dc.DataCenterVO;
import com.cloud.dc.Pod;
+import com.cloud.dc.dao.DataCenterDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
@@ -67,6 +70,10 @@ public class BaremetalPxeElement extends AdapterBase implements NetworkElement {
VMInstanceDao _vmDao;
@Inject
NicDao _nicDao;
+ @Inject
+ BaremetalVlanManager vlanMgr;
+ @Inject
+ DataCenterDao zoneDao;
static {
Capability cap = new Capability(BaremetalPxeManager.BAREMETAL_PXE_CAPABILITY);
@@ -133,15 +140,31 @@ public class BaremetalPxeElement extends AdapterBase implements NetworkElement {
}
}
- return false;
+ if (dest.getDataCenter().getNetworkType() == DataCenter.NetworkType.Advanced){
+ prepareVlan(network, dest);
+ }
+
+ return true;
+ }
+
+ private void prepareVlan(Network network, DeployDestination dest) {
+ vlanMgr.prepareVlan(network, dest);
}
@Override
public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm, ReservationContext context) throws ConcurrentOperationException,
ResourceUnavailableException {
+ DataCenterVO dc = zoneDao.findById(vm.getVirtualMachine().getDataCenterId());
+ if (dc.getNetworkType() == DataCenter.NetworkType.Advanced) {
+ releaseVlan(network, vm);
+ }
return true;
}
+ private void releaseVlan(Network network, VirtualMachineProfile vm) {
+ vlanMgr.releaseVlan(network, vm);
+ }
+
@Override
public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
return true;
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalSwitchBackend.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalSwitchBackend.java
new file mode 100644
index 00000000000..1ad6ee4cade
--- /dev/null
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalSwitchBackend.java
@@ -0,0 +1,34 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// Automatically generated by addcopyright.py at 01/29/2013
+// Apache License, Version 2.0 (the "License"); you may not use this
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.baremetal.networkservice;
+
+/**
+ * Created by frank on 9/2/14.
+ */
+public interface BaremetalSwitchBackend {
+ String getSwitchBackendType();
+
+ void prepareVlan(BaremetalVlanStruct struct);
+
+ void removePortFromVlan(BaremetalVlanStruct struct);
+}
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalVlanStruct.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalVlanStruct.java
new file mode 100644
index 00000000000..32d9b33a344
--- /dev/null
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalVlanStruct.java
@@ -0,0 +1,92 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// Automatically generated by addcopyright.py at 01/29/2013
+// Apache License, Version 2.0 (the "License"); you may not use this
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.baremetal.networkservice;
+
+/**
+ * Created by frank on 9/2/14.
+ */
+public class BaremetalVlanStruct {
+ private String switchType;
+ private String switchIp;
+ private String switchUsername;
+ private String switchPassword;
+ private String hostMac;
+ private String port;
+ private int vlan;
+
+ public String getSwitchType() {
+ return switchType;
+ }
+
+ public void setSwitchType(String switchType) {
+ this.switchType = switchType;
+ }
+
+ public String getSwitchIp() {
+ return switchIp;
+ }
+
+ public void setSwitchIp(String switchIp) {
+ this.switchIp = switchIp;
+ }
+
+ public String getSwitchUsername() {
+ return switchUsername;
+ }
+
+ public void setSwitchUsername(String switchUsername) {
+ this.switchUsername = switchUsername;
+ }
+
+ public String getSwitchPassword() {
+ return switchPassword;
+ }
+
+ public void setSwitchPassword(String switchPassword) {
+ this.switchPassword = switchPassword;
+ }
+
+ public String getHostMac() {
+ return hostMac;
+ }
+
+ public void setHostMac(String hostMac) {
+ this.hostMac = hostMac;
+ }
+
+ public String getPort() {
+ return port;
+ }
+
+ public void setPort(String port) {
+ this.port = port;
+ }
+
+ public int getVlan() {
+ return vlan;
+ }
+
+ public void setVlan(int vlan) {
+ this.vlan = vlan;
+ }
+}
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/Force10BaremetalSwitchBackend.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/Force10BaremetalSwitchBackend.java
new file mode 100644
index 00000000000..9009b02d3fb
--- /dev/null
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/Force10BaremetalSwitchBackend.java
@@ -0,0 +1,196 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// Automatically generated by addcopyright.py at 01/29/2013
+// Apache License, Version 2.0 (the "License"); you may not use this
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.baremetal.networkservice;
+
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.xmlobject.XmlObject;
+import com.cloud.utils.xmlobject.XmlObjectParser;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by frank on 9/2/14.
+ */
+public class Force10BaremetalSwitchBackend implements BaremetalSwitchBackend {
+ private Logger logger = Logger.getLogger(Force10BaremetalSwitchBackend.class);
+ public static final String TYPE = "Force10";
+
+ RestTemplate rest = new RestTemplate();
+
+ private String buildLink(String switchIp, Integer vlan) {
+ UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
+ builder.scheme("http");
+ builder.host(switchIp);
+ builder.port(8008);
+ builder.path("/api/running/ftos/interface/vlan");
+ if (vlan != null) {
+ builder.path(vlan.toString());
+ }
+ return builder.build().toUriString();
+ }
+
+ @Override
+ public String getSwitchBackendType() {
+ return TYPE;
+ }
+
+ @Override
+ public void prepareVlan(BaremetalVlanStruct struct) {
+ String link = buildLink(struct.getSwitchIp(), struct.getVlan());
+ HttpHeaders headers = createBasicAuthenticationHeader(struct);
+ HttpEntity request = new HttpEntity<>(headers);
+ ResponseEntity rsp = rest.exchange(link, HttpMethod.GET, request, String.class);
+
+ if (rsp.getStatusCode() == HttpStatus.NOT_FOUND) {
+ PortInfo port = new PortInfo(struct);
+ XmlObject xml = new XmlObject("vlan").putElement("vlan-id", String.valueOf(struct.getVlan())).putElement("tagged",
+ new XmlObject(port.interfaceType).putElement("name", port.port)
+ ).putElement("shutdown", "false");
+ request = new HttpEntity<>(xml.toString(), headers);
+ link = buildLink(struct.getSwitchIp(), null);
+ rsp = rest.exchange(link, HttpMethod.GET, request, String.class);
+ if (rsp.getStatusCode() != HttpStatus.OK) {
+ throw new CloudRuntimeException(String.format("unable to create vlan[%s] on force10 switch[ip:%s]. HTTP status code:%s, body dump:%s",
+ struct.getVlan(), rsp.getStatusCode(), struct.getSwitchIp(), rsp.getBody()));
+ }
+ } else if (rsp.getStatusCode() == HttpStatus.OK) {
+ PortInfo port = new PortInfo(struct);
+ XmlObject xml = XmlObjectParser.parseFromString((String)rsp.getBody());
+ List ports = xml.getAsList("tagged.tengigabitethernet");
+ ports.addAll(xml.getAsList("tagged.gigabitethernet"));
+ ports.addAll(xml.getAsList("tagged.fortyGigE"));
+ for (XmlObject pxml : ports) {
+ XmlObject name = pxml.get("name");
+ if (port.port.equals(name.getText())) {
+ logger.debug(String.format("port[%s] has joined in vlan[%s], no need to program again", struct.getPort(), struct.getVlan()));
+ return;
+ }
+ }
+
+ XmlObject tag = xml.get("tagged");
+ tag.putElement(port.interfaceType, new XmlObject("name").setText(port.port));
+ request = new HttpEntity<>(xml.toString(), headers);
+ link = buildLink(struct.getSwitchIp(), struct.getVlan());
+ rsp = rest.exchange(link, HttpMethod.PUT, request, String.class);
+ if (rsp.getStatusCode() != HttpStatus.NO_CONTENT) {
+ throw new CloudRuntimeException(String.format("failed to program vlan[%s] for port[%s] on force10[ip:%s]. http status:%s, body dump:%s",
+ struct.getVlan(), struct.getPort(), struct.getSwitchIp(), rsp.getStatusCode(), rsp.getBody()));
+ }
+ } else {
+ throw new CloudRuntimeException(String.format("force10[ip:%s] returns unexpected error[%s] when http getting %s, body dump:%s",
+ struct.getSwitchIp(), rsp.getStatusCode(), link, rsp.getBody()));
+ }
+ }
+
+ @Override
+ public void removePortFromVlan(BaremetalVlanStruct struct) {
+ String link = buildLink(struct.getSwitchIp(), struct.getVlan());
+ HttpHeaders headers = createBasicAuthenticationHeader(struct);
+ HttpEntity request = new HttpEntity<>(headers);
+ ResponseEntity rsp = rest.exchange(link, HttpMethod.GET, request, String.class);
+ if (rsp.getStatusCode() == HttpStatus.NOT_FOUND) {
+ 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()));
+ } else if (rsp.getStatusCode() == HttpStatus.OK) {
+ PortInfo port = new PortInfo(struct);
+ XmlObject xml = XmlObjectParser.parseFromString((String)rsp.getBody());
+ List ports = xml.getAsList("tagged.tengigabitethernet");
+ ports.addAll(xml.getAsList("tagged.gigabitethernet"));
+ ports.addAll(xml.getAsList("tagged.fortyGigE"));
+ List newPorts = new ArrayList<>();
+ boolean needRemove = false;
+ for (XmlObject pxml : ports) {
+ XmlObject name = pxml.get("name");
+ if (port.port.equals(name.getText())) {
+ needRemove = true;
+ continue;
+ }
+
+ newPorts.add(pxml);
+ }
+
+ if (!needRemove) {
+ return;
+ }
+
+ xml.putElement("tagged", newPorts);
+
+ request = new HttpEntity<>(xml.toString(), headers);
+ rsp = rest.exchange(link, HttpMethod.PUT, request, String.class);
+ if (rsp.getStatusCode() != HttpStatus.NO_CONTENT) {
+ throw new CloudRuntimeException(String.format("failed to program vlan[%s] for port[%s] on force10[ip:%s]. http status:%s, body dump:%s",
+ struct.getVlan(), struct.getPort(), struct.getSwitchIp(), rsp.getStatusCode(), rsp.getBody()));
+ } else {
+ logger.debug(String.format("removed port[%s] from vlan[%s] on force10[ip:%s]", struct.getPort(), struct.getVlan(), struct.getSwitchIp()));
+ }
+ } else {
+ throw new CloudRuntimeException(String.format("force10[ip:%s] returns unexpected error[%s] when http getting %s, body dump:%s",
+ struct.getSwitchIp(), rsp.getStatusCode(), link, rsp.getBody()));
+ }
+ }
+
+ private HttpHeaders createBasicAuthenticationHeader(BaremetalVlanStruct struct) {
+ String plainCreds = String.format("%s:%s", struct.getSwitchUsername(), struct.getSwitchPassword());
+ byte[] plainCredsBytes = plainCreds.getBytes();
+ byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
+ String base64Creds = new String(base64CredsBytes);
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("Authorization", "Basic " + base64Creds);
+ return headers;
+ }
+
+ private class PortInfo {
+ static final String G_IFACE = "gigabitethernet";
+ static final String TEN_G_IFACE = "tengigabitethernet";
+ static final String FOURTY_G_IFACE = "fortyGigE";
+
+ private String interfaceType;
+ private String port;
+
+ PortInfo(BaremetalVlanStruct struct) {
+ String[] ps = StringUtils.split(struct.getPort(), ":");
+ if (ps.length == 1) {
+ interfaceType = TEN_G_IFACE;
+ port = ps[0];
+ } else if (ps.length == 2) {
+ interfaceType = ps[0];
+ if (!interfaceType.equals(G_IFACE) && !interfaceType.equals(TEN_G_IFACE) && !interfaceType.equals(FOURTY_G_IFACE)) {
+ throw new CloudRuntimeException(String.format("wrong port definition[%s]. The prefix must be one of [%s,%s,%s]", struct.getPort(), G_IFACE, TEN_G_IFACE, FOURTY_G_IFACE));
+ }
+ port = ps[1];
+ } else {
+ throw new CloudRuntimeException(String.format("wrong port definition[%s]. Force10 port should be in format of interface_type:port_identity, for example: tengigabitethernet:1/3", struct.getPort()));
+ }
+ }
+ }
+}
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index 85277386f82..1012c4d6c46 100755
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -1841,6 +1841,14 @@ public enum Config {
"The maximum number of retrying times to search for an available IPv6 address in the table",
null),
+ BaremetalEnableCompleteNotification(
+ "Advanced",
+ ManagementServer.class,
+ Boolean.class,
+ "baremetal.provision.done.notification",
+ "false",
+ "Enable provision done notification through virtual router",
+ null),
BaremetalPeerHypervisorType(
"Advanced",
ManagementServer.class,
diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java
index 9a7bc480cb8..9f34d1f661e 100755
--- a/server/src/com/cloud/network/NetworkServiceImpl.java
+++ b/server/src/com/cloud/network/NetworkServiceImpl.java
@@ -16,46 +16,6 @@
// under the License.
package com.cloud.network;
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.URI;
-import java.net.UnknownHostException;
-import java.security.InvalidParameterException;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.UUID;
-
-import javax.ejb.Local;
-import javax.inject.Inject;
-import javax.naming.ConfigurationException;
-
-import org.apache.cloudstack.acl.ControlledEntity.ACLType;
-import org.apache.cloudstack.acl.SecurityChecker.AccessType;
-import org.apache.cloudstack.api.command.admin.network.CreateNetworkCmdByAdmin;
-import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
-import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd;
-import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
-import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
-import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
-import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
-import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
-import org.apache.cloudstack.context.CallContext;
-import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
-import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
-import org.apache.log4j.Logger;
-
import com.cloud.api.ApiDBUtils;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
@@ -163,6 +123,7 @@ import com.cloud.utils.db.DB;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.JoinBuilder;
+import com.cloud.utils.db.QueryBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.SearchCriteria.Op;
@@ -189,6 +150,44 @@ import com.cloud.vm.dao.NicSecondaryIpDao;
import com.cloud.vm.dao.NicSecondaryIpVO;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
+import org.apache.cloudstack.acl.ControlledEntity.ACLType;
+import org.apache.cloudstack.acl.SecurityChecker.AccessType;
+import org.apache.cloudstack.api.command.admin.network.CreateNetworkCmdByAdmin;
+import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd;
+import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd;
+import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
+import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
+import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
+import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
+import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.network.element.InternalLoadBalancerElementService;
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.UnknownHostException;
+import java.security.InvalidParameterException;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.UUID;
/**
* NetworkServiceImpl implements NetworkService.
@@ -3854,11 +3853,20 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalUserdataProvider", null, null);
} else if (dvo.getNetworkType() == NetworkType.Advanced) {
addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalPxeProvider", null, null);
+ enableBaremetalProvider("BaremetalPxeProvider");
}
return null;
}
+ private void enableBaremetalProvider(String providerName) {
+ QueryBuilder q = QueryBuilder.create(PhysicalNetworkServiceProviderVO.class);
+ q.and(q.entity().getProviderName(), SearchCriteria.Op.EQ, providerName);
+ PhysicalNetworkServiceProviderVO provider = q.find();
+ provider.setState(PhysicalNetworkServiceProvider.State.Enabled);
+ _pNSPDao.update(provider.getId(), provider);
+ }
+
protected boolean isNetworkSystem(Network network) {
NetworkOffering no = _networkOfferingDao.findByIdIncludingRemoved(network.getNetworkOfferingId());
if (no.isSystemOnly()) {
diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index 21a231746d4..7b8f7fac3b8 100755
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -17,52 +17,6 @@
package com.cloud.network.router;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TimeZone;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import javax.ejb.Local;
-import javax.inject.Inject;
-import javax.naming.ConfigurationException;
-
-import org.apache.log4j.Logger;
-
-import org.apache.cloudstack.alert.AlertService;
-import org.apache.cloudstack.alert.AlertService.AlertType;
-import org.apache.cloudstack.api.command.admin.router.RebootRouterCmd;
-import org.apache.cloudstack.api.command.admin.router.UpgradeRouterCmd;
-import org.apache.cloudstack.api.command.admin.router.UpgradeRouterTemplateCmd;
-import org.apache.cloudstack.config.ApiServiceConfiguration;
-import org.apache.cloudstack.context.CallContext;
-import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
-import org.apache.cloudstack.framework.config.ConfigDepot;
-import org.apache.cloudstack.framework.config.ConfigKey;
-import org.apache.cloudstack.framework.config.Configurable;
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
-import org.apache.cloudstack.framework.jobs.AsyncJobManager;
-import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
-import org.apache.cloudstack.managed.context.ManagedContextRunnable;
-import org.apache.cloudstack.utils.identity.ManagementServerNode;
-
import com.cloud.agent.AgentManager;
import com.cloud.agent.Listener;
import com.cloud.agent.api.AgentControlAnswer;
@@ -255,6 +209,7 @@ import com.cloud.utils.db.EntityManager;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.JoinBuilder;
+import com.cloud.utils.db.QueryBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
@@ -288,6 +243,49 @@ import com.cloud.vm.dao.NicIpAliasVO;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.UserVmDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
+import org.apache.cloudstack.alert.AlertService;
+import org.apache.cloudstack.alert.AlertService.AlertType;
+import org.apache.cloudstack.api.command.admin.router.RebootRouterCmd;
+import org.apache.cloudstack.api.command.admin.router.UpgradeRouterCmd;
+import org.apache.cloudstack.api.command.admin.router.UpgradeRouterTemplateCmd;
+import org.apache.cloudstack.config.ApiServiceConfiguration;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
+import org.apache.cloudstack.framework.config.ConfigDepot;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.Configurable;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
+import org.apache.cloudstack.framework.jobs.AsyncJobManager;
+import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
+import org.apache.cloudstack.managed.context.ManagedContextRunnable;
+import org.apache.cloudstack.utils.identity.ManagementServerNode;
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TimeZone;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
/**
* VirtualNetworkApplianceManagerImpl manages the different types of virtual network appliances available in the Cloud Stack.
@@ -2320,6 +2318,18 @@ VirtualMachineGuru, Listener, Configurable, StateListener acntq = QueryBuilder.create(UserVO.class);
+ acntq.and(acntq.entity().getUsername(), SearchCriteria.Op.EQ, "baremetal-system-account");
+ UserVO user = acntq.find();
+ if (user == null) {
+ s_logger.warn(String.format("global setting[baremetal.provision.done.notification] is enabled but user baremetal-system-account is not found. Baremetal provision done notification will not be enabled"));
+ } else {
+ buf.append(String.format(" baremetalnotificationsecuritykey=%s", user.getSecretKey()));
+ buf.append(String.format(" baremetalnotificationapikey=%s", user.getApiKey()));
+ }
+ }
+
if (s_logger.isDebugEnabled()) {
s_logger.debug("Boot Args for " + profile + ": " + buf.toString());
}
diff --git a/utils/src/com/cloud/utils/xmlobject/XmlObject.java b/utils/src/com/cloud/utils/xmlobject/XmlObject.java
index e03a84dd6bf..e4e4363cd7e 100755
--- a/utils/src/com/cloud/utils/xmlobject/XmlObject.java
+++ b/utils/src/com/cloud/utils/xmlobject/XmlObject.java
@@ -66,6 +66,10 @@ public class XmlObject {
return this;
}
+ public void removeElement(String key) {
+ elements.remove(key);
+ }
+
private Object recurGet(XmlObject obj, Iterator it) {
String key = it.next();
Object e = obj.elements.get(key);