cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From frankzh...@apache.org
Subject [3/3] git commit: updated refs/heads/master to 10544e2
Date Fri, 05 Sep 2014 23:24:24 GMT
CLOUDSTACK-6278
Baremetal Advanced Networking support


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/10544e28
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/10544e28
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/10544e28

Branch: refs/heads/master
Commit: 10544e287b0fc8d62729ee226b12063cefbbdae8
Parents: 1973324
Author: Frank.Zhang <frank.zhang@citrix.com>
Authored: Fri Sep 5 16:28:08 2014 -0700
Committer: Frank.Zhang <frank.zhang@citrix.com>
Committed: Fri Sep 5 16:28:34 2014 -0700

----------------------------------------------------------------------
 .../core/spring-baremetal-core-context.xml      |   1 +
 .../cloud/baremetal/manager/BaremetalRct.java   |   6 +-
 .../baremetal/manager/BaremetalVlanManager.java |   7 +
 .../manager/BaremetalVlanManagerImpl.java       | 112 ++++++++++-
 .../networkservice/BaremetalPxeElement.java     |  25 ++-
 .../networkservice/BaremetalSwitchBackend.java  |  34 ++++
 .../networkservice/BaremetalVlanStruct.java     |  92 +++++++++
 .../Force10BaremetalSwitchBackend.java          | 196 +++++++++++++++++++
 server/src/com/cloud/configuration/Config.java  |   8 +
 .../com/cloud/network/NetworkServiceImpl.java   |  88 +++++----
 .../VirtualNetworkApplianceManagerImpl.java     | 102 +++++-----
 .../com/cloud/utils/xmlobject/XmlObject.java    |   4 +
 12 files changed, 577 insertions(+), 98 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/10544e28/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml
----------------------------------------------------------------------
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 e1a21bc..ae28efa
--- 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 @@
 
     <bean id="BaremetalManager" class="com.cloud.baremetal.manager.BaremetalManagerImpl"
/>
     <bean id="BaremetalVlanManager" class="com.cloud.baremetal.manager.BaremetalVlanManagerImpl"
/>
+    <bean id="Force10BaremetalSwitchBackend" class="com.cloud.baremetal.networkservice.Force10BaremetalSwitchBackend"
/>
 
     <bean id="BaremetalKickStartPxeService"
         class="com.cloud.baremetal.networkservice.BaremetalKickStartServiceImpl" />

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/10544e28/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalRct.java
----------------------------------------------------------------------
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 9ed7cf4..96e7865 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;
         }
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/10544e28/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManager.java
----------------------------------------------------------------------
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 13e61fa..1662668 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);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/10544e28/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManagerImpl.java
----------------------------------------------------------------------
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 f307af4..0334fb3 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<String, BaremetalSwitchBackend> backends = new HashMap<>();
+
+    private class RackPair {
+        BaremetalRct.Rack rack;
+        BaremetalRct.HostEntry host;
+    }
+
     @Override
     public BaremetalRctResponse addRct(AddBaremetalRctCmd cmd) {
         try {
@@ -88,10 +108,94 @@ public class BaremetalVlanManagerImpl extends ManagerBase implements
BaremetalVl
     }
 
     @Override
+    public void prepareVlan(Network nw, DeployDestination destHost) {
+        List<BaremetalRctVO> 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<BaremetalRctVO> 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<Class<?>> getCommands() {
+        List<Class<?>> cmds = new ArrayList<Class<?>>();
+        cmds.add(AddBaremetalRctCmd.class);
+        return cmds;
+    }
+
     @Override
     public boolean start() {
         QueryBuilder<AccountVO> 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<Class<?>> getCommands() {
-        List<Class<?>> cmds = new ArrayList<Class<?>>();
-        cmds.add(AddBaremetalRctCmd.class);
-        return cmds;
-    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/10544e28/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java
----------------------------------------------------------------------
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 b314bdb..9b835bf 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;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/10544e28/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalSwitchBackend.java
----------------------------------------------------------------------
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 0000000..1ad6ee4
--- /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);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/10544e28/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalVlanStruct.java
----------------------------------------------------------------------
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 0000000..32d9b33
--- /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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/10544e28/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/Force10BaremetalSwitchBackend.java
----------------------------------------------------------------------
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 0000000..9009b02
--- /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<String> 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<XmlObject> ports = xml.getAsList("tagged.tengigabitethernet");
+            ports.addAll(xml.<XmlObject>getAsList("tagged.gigabitethernet"));
+            ports.addAll(xml.<XmlObject>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<String> 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<XmlObject> ports = xml.getAsList("tagged.tengigabitethernet");
+            ports.addAll(xml.<XmlObject>getAsList("tagged.gigabitethernet"));
+            ports.addAll(xml.<XmlObject>getAsList("tagged.fortyGigE"));
+            List<XmlObject> 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()));
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/10544e28/server/src/com/cloud/configuration/Config.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index 8527738..1012c4d 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,

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/10544e28/server/src/com/cloud/network/NetworkServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java
index 9a7bc48..9f34d1f 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<PhysicalNetworkServiceProviderVO> 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()) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/10544e28/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index 21a2317..7b8f7fa 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<State,
VirtualMachine.
             }
         }
 
+        if (Boolean.valueOf(_configDao.getValue("baremetal.provision.done.notification")))
{
+            QueryBuilder<UserVO> 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());
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/10544e28/utils/src/com/cloud/utils/xmlobject/XmlObject.java
----------------------------------------------------------------------
diff --git a/utils/src/com/cloud/utils/xmlobject/XmlObject.java b/utils/src/com/cloud/utils/xmlobject/XmlObject.java
index e03a84d..e4e4363 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<String> it) {
         String key = it.next();
         Object e = obj.elements.get(key);


Mime
View raw message