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);