_authcookie variable.
+ *
+ * The method returns false if the login failed or the connection could not be made.
+ *
+ */
+ protected void login() throws BigSwitchVnsApiException {
+ return;
+ }
+
+ public void createNetwork(Network network)
+ throws BigSwitchVnsApiException {
+ String uri = _nsBaseUri + "/tenant/" + network.getTenant_id() + "/network";
+ executeCreateObject(network, new TypeToken(){}.getType(),
+ uri, Collections.emptyMap());
+ }
+
+ public void deleteNetwork(String tenantId, String networkId) throws BigSwitchVnsApiException {
+ String uri = _nsBaseUri + "/tenant/" + tenantId + "/networks/" + networkId;
+ executeDeleteObject(uri);
+ }
+
+ public void createPort(String networkUuid, Port port)
+ throws BigSwitchVnsApiException {
+ String uri = _nsBaseUri + "/tenant/" + port.getTenant_id() + "/networks/" + networkUuid + "/ports";
+ executeCreateObject(port, new TypeToken(){}.getType(),
+ uri, Collections.emptyMap());
+ }
+
+ public void modifyPort(String networkId, Port port)
+ throws BigSwitchVnsApiException {
+ String uri = _nsBaseUri + "/tenant/" + port.getTenant_id() + "/networks/" + networkId + "/ports";
+ executeUpdateObject(port, uri, Collections.emptyMap());
+ }
+
+ public void deletePort(String tenantId, String networkId, String portId)
+ throws BigSwitchVnsApiException {
+ String uri = _nsBaseUri + "/tenant/" + tenantId + "/networks/" + networkId + "/ports/" + portId;
+ executeDeleteObject(uri);
+ }
+
+ public void modifyPortAttachment(String tenantId,
+ String networkId,
+ String portId,
+ Attachment attachment) throws BigSwitchVnsApiException {
+ String uri = _nsBaseUri + "/tenant/" + tenantId + "/networks/" + networkId + "/ports/" + portId + "/attachment";
+ executeUpdateObject(attachment, uri, Collections.emptyMap());
+ }
+
+ public void deletePortAttachment(String tenantId, String networkId, String portId)
+ throws BigSwitchVnsApiException {
+ String uri = _nsBaseUri + "/tenant/" + tenantId + "/networks/" + networkId + "/ports/" + portId + "/attachment";
+ executeDeleteObject(uri);
+ }
+
+ public ControlClusterStatus getControlClusterStatus() throws BigSwitchVnsApiException {
+ String uri = _controllerBaseUri + "/health/json";
+ ControlClusterStatus ccs = executeRetrieveObject(new TypeToken(){}.getType(),
+ uri, 80, null);
+
+ return ccs;
+ }
+
+ protected void executeUpdateObject(T newObject, String uri, Map parameters)
+ throws BigSwitchVnsApiException {
+ if (_host == null || _host.isEmpty()) {
+ throw new BigSwitchVnsApiException("Hostname is null or empty");
+ }
+
+ Gson gson = new Gson();
+
+ PutMethod pm = (PutMethod) createMethod("put", uri, 80);
+ pm.setRequestHeader(CONTENT_TYPE, CONTENT_JSON);
+ pm.setRequestHeader(HTTP_HEADER_INSTANCE_ID, CLOUDSTACK_INSTANCE_ID);
+ try {
+ pm.setRequestEntity(new StringRequestEntity(
+ gson.toJson(newObject), CONTENT_JSON, null));
+ } catch (UnsupportedEncodingException e) {
+ throw new BigSwitchVnsApiException("Failed to encode json request body", e);
+ }
+
+ executeMethod(pm);
+
+ if (pm.getStatusCode() != HttpStatus.SC_OK) {
+ String errorMessage = responseToErrorMessage(pm);
+ pm.releaseConnection();
+ s_logger.error("Failed to update object : " + errorMessage);
+ throw new BigSwitchVnsApiException("Failed to update object : " + errorMessage);
+ }
+ pm.releaseConnection();
+ }
+
+ protected void executeCreateObject(T newObject, Type returnObjectType, String uri,
+ Map parameters)
+ throws BigSwitchVnsApiException {
+ if (_host == null || _host.isEmpty()) {
+ throw new BigSwitchVnsApiException("Hostname is null or empty");
+ }
+
+ Gson gson = new Gson();
+
+ PostMethod pm = (PostMethod) createMethod("post", uri, 80);
+ pm.setRequestHeader(CONTENT_TYPE, CONTENT_JSON);
+ pm.setRequestHeader(HTTP_HEADER_INSTANCE_ID, CLOUDSTACK_INSTANCE_ID);
+ try {
+ pm.setRequestEntity(new StringRequestEntity(
+ gson.toJson(newObject), CONTENT_JSON, null));
+ } catch (UnsupportedEncodingException e) {
+ throw new BigSwitchVnsApiException("Failed to encode json request body", e);
+ }
+
+ executeMethod(pm);
+
+ if (pm.getStatusCode() != HttpStatus.SC_OK) {
+ String errorMessage = responseToErrorMessage(pm);
+ pm.releaseConnection();
+ s_logger.error("Failed to create object : " + errorMessage);
+ throw new BigSwitchVnsApiException("Failed to create object : " + errorMessage);
+ }
+ pm.releaseConnection();
+
+ return;
+ }
+
+ protected void executeDeleteObject(String uri) throws BigSwitchVnsApiException {
+ if (_host == null || _host.isEmpty()) {
+ throw new BigSwitchVnsApiException("Hostname is null or empty");
+ }
+
+ DeleteMethod dm = (DeleteMethod) createMethod("delete", uri, 80);
+ dm.setRequestHeader(CONTENT_TYPE, CONTENT_JSON);
+ dm.setRequestHeader(HTTP_HEADER_INSTANCE_ID, CLOUDSTACK_INSTANCE_ID);
+
+ executeMethod(dm);
+
+ if (dm.getStatusCode() != HttpStatus.SC_OK) {
+ String errorMessage = responseToErrorMessage(dm);
+ dm.releaseConnection();
+ s_logger.error("Failed to delete object : " + errorMessage);
+ throw new BigSwitchVnsApiException("Failed to delete object : " + errorMessage);
+ }
+ dm.releaseConnection();
+ }
+
+ @SuppressWarnings("unchecked")
+ protected T executeRetrieveObject(Type returnObjectType, String uri, int port, Map parameters)
+ throws BigSwitchVnsApiException {
+ if (_host == null || _host.isEmpty()) {
+ throw new BigSwitchVnsApiException("Hostname is null or empty");
+ }
+
+ GetMethod gm = (GetMethod) createMethod("get", uri, port);
+ gm.setRequestHeader(CONTENT_TYPE, CONTENT_JSON);
+ gm.setRequestHeader(HTTP_HEADER_INSTANCE_ID, CLOUDSTACK_INSTANCE_ID);
+
+ if (parameters != null && !parameters.isEmpty()) {
+ List nameValuePairs = new ArrayList(parameters.size());
+ for (Entry e : parameters.entrySet()) {
+ nameValuePairs.add(new NameValuePair(e.getKey(), e.getValue()));
+ }
+ gm.setQueryString(nameValuePairs.toArray(new NameValuePair[0]));
+ }
+
+ executeMethod(gm);
+
+ if (gm.getStatusCode() != HttpStatus.SC_OK) {
+ String errorMessage = responseToErrorMessage(gm);
+ gm.releaseConnection();
+ s_logger.error("Failed to retrieve object : " + errorMessage);
+ throw new BigSwitchVnsApiException("Failed to retrieve object : " + errorMessage);
+ }
+
+ Gson gson = new Gson();
+ T returnValue;
+ try {
+ returnValue = (T)gson.fromJson(gm.getResponseBodyAsString(), returnObjectType);
+ } catch (IOException e) {
+ s_logger.error("IOException while retrieving response body",e);
+ throw new BigSwitchVnsApiException(e);
+ } finally {
+ gm.releaseConnection();
+ }
+ return returnValue;
+ }
+
+ protected void executeMethod(HttpMethodBase method) throws BigSwitchVnsApiException {
+ try {
+ _client.executeMethod(method);
+ if (method.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {
+ method.releaseConnection();
+ // login and try again
+ login();
+ _client.executeMethod(method);
+ }
+ } catch (HttpException e) {
+ s_logger.error("HttpException caught while trying to connect to the BigSwitch Controller", e);
+ method.releaseConnection();
+ throw new BigSwitchVnsApiException("API call to BigSwitch Controller Failed", e);
+ } catch (IOException e) {
+ s_logger.error("IOException caught while trying to connect to the BigSwitch Controller", e);
+ method.releaseConnection();
+ throw new BigSwitchVnsApiException("API call to BigSwitch Controller Failed", e);
+ }
+ }
+
+ private String responseToErrorMessage(HttpMethodBase method) {
+ assert method.isRequestSent() : "no use getting an error message unless the request is sent";
+
+ if ("text/html".equals(method.getResponseHeader(CONTENT_TYPE).getValue())) {
+ // The error message is the response content
+ // Safety margin of 1024 characters, anything longer is probably useless
+ // and will clutter the logs
+ try {
+ return method.getResponseBodyAsString(1024);
+ } catch (IOException e) {
+ s_logger.debug("Error while loading response body", e);
+ }
+ }
+
+ // The default
+ return method.getStatusText();
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/BigSwitchVnsApiException.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/BigSwitchVnsApiException.java
new file mode 100644
index 00000000000..49c32382936
--- /dev/null
+++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/BigSwitchVnsApiException.java
@@ -0,0 +1,39 @@
+// 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.
+package com.cloud.network.bigswitch;
+
+public class BigSwitchVnsApiException extends Exception {
+
+
+ private static final long serialVersionUID = -5864952230870945604L;
+
+ public BigSwitchVnsApiException() {
+ }
+
+ public BigSwitchVnsApiException(String message) {
+ super(message);
+ }
+
+ public BigSwitchVnsApiException(Throwable cause) {
+ super(cause);
+ }
+
+ public BigSwitchVnsApiException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/ControlClusterStatus.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/ControlClusterStatus.java
new file mode 100644
index 00000000000..9181afdc509
--- /dev/null
+++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/ControlClusterStatus.java
@@ -0,0 +1,25 @@
+// 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.
+package com.cloud.network.bigswitch;
+
+public class ControlClusterStatus {
+ private boolean healthy;
+
+ public boolean getStatus() {
+ return healthy;
+ }
+}
diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/Network.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/Network.java
new file mode 100644
index 00000000000..c89c6932d31
--- /dev/null
+++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/Network.java
@@ -0,0 +1,74 @@
+// 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.
+package com.cloud.network.bigswitch;
+
+public class Network {
+ private String id;
+ private String name;
+ private String tenant_id;
+ private int vlan;
+ private String gateway;
+ private String state;
+
+ public String getUuid() {
+ return id;
+ }
+
+ public void setUuid(String id) {
+ this.id = id;
+ }
+
+ public String getDisplay_name() {
+ return name;
+ }
+
+ public void setDisplay_name(String display_name) {
+ this.name = display_name;
+ }
+
+ public String getTenant_id() {
+ return tenant_id;
+ }
+
+ public void setTenant_id(String tenant_id) {
+ this.tenant_id = tenant_id;
+ }
+
+ public int getVlan() {
+ return vlan;
+ }
+
+ public void setVlan(int vlan) {
+ this.vlan = vlan;
+ }
+
+ public String getGateway() {
+ return gateway;
+ }
+
+ public void setGateway(String gateway) {
+ this.gateway = gateway;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+}
diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/Port.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/Port.java
new file mode 100644
index 00000000000..bf749d084e2
--- /dev/null
+++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/Port.java
@@ -0,0 +1,56 @@
+// 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.
+package com.cloud.network.bigswitch;
+
+public class Port {
+ private String id;
+ private String name;
+ private String tenant_id;
+ private String state;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getTenant_id() {
+ return tenant_id;
+ }
+
+ public void setTenant_id(String tenant_id) {
+ this.tenant_id = tenant_id;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+}
diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/dao/BigSwitchVnsDao.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/dao/BigSwitchVnsDao.java
new file mode 100644
index 00000000000..d9bbf9da737
--- /dev/null
+++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/dao/BigSwitchVnsDao.java
@@ -0,0 +1,32 @@
+// 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.
+package com.cloud.network.dao;
+
+import java.util.List;
+
+import com.cloud.network.BigSwitchVnsDeviceVO;
+import com.cloud.utils.db.GenericDao;
+
+public interface BigSwitchVnsDao extends GenericDao{
+ /**
+ * list all the bigswitch Vns devices added in to this physical network
+ * @param physicalNetworkId physical Network Id
+ * @return list of BigSwitchVnsDeviceVO for this physical network.
+ */
+ List listByPhysicalNetwork(long physicalNetworkId);
+
+}
diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/dao/BigSwitchVnsDaoImpl.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/dao/BigSwitchVnsDaoImpl.java
new file mode 100644
index 00000000000..955bdda128c
--- /dev/null
+++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/dao/BigSwitchVnsDaoImpl.java
@@ -0,0 +1,48 @@
+// 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.
+package com.cloud.network.dao;
+
+import java.util.List;
+
+import javax.ejb.Local;
+
+import com.cloud.network.BigSwitchVnsDeviceVO;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.SearchCriteria.Op;
+
+@Local(value=BigSwitchVnsDao.class)
+public class BigSwitchVnsDaoImpl extends GenericDaoBase
+ implements BigSwitchVnsDao {
+
+ protected final SearchBuilder physicalNetworkIdSearch;
+
+ public BigSwitchVnsDaoImpl() {
+ physicalNetworkIdSearch = createSearchBuilder();
+ physicalNetworkIdSearch.and("physicalNetworkId", physicalNetworkIdSearch.entity().getPhysicalNetworkId(), Op.EQ);
+ physicalNetworkIdSearch.done();
+ }
+
+ @Override
+ public List listByPhysicalNetwork(long physicalNetworkId) {
+ SearchCriteria sc = physicalNetworkIdSearch.create();
+ sc.setParameters("physicalNetworkId", physicalNetworkId);
+ return search(sc, null);
+ }
+
+}
diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/element/BigSwitchVnsElement.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/element/BigSwitchVnsElement.java
new file mode 100644
index 00000000000..35e4bdbbd3f
--- /dev/null
+++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/element/BigSwitchVnsElement.java
@@ -0,0 +1,543 @@
+// 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.
+package com.cloud.network.element;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice;
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.CreateVnsPortAnswer;
+import com.cloud.agent.api.CreateVnsPortCommand;
+import com.cloud.agent.api.DeleteVnsPortAnswer;
+import com.cloud.agent.api.DeleteVnsPortCommand;
+import com.cloud.agent.api.StartupBigSwitchVnsCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.api.ApiDBUtils;
+import com.cloud.api.commands.AddBigSwitchVnsDeviceCmd;
+import com.cloud.api.commands.DeleteBigSwitchVnsDeviceCmd;
+import com.cloud.api.commands.ListBigSwitchVnsDevicesCmd;
+import com.cloud.api.commands.VnsConstants;
+import com.cloud.api.response.BigSwitchVnsDeviceResponse;
+import com.cloud.configuration.ConfigurationManager;
+import com.cloud.dc.dao.VlanDao;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.host.DetailVO;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.host.dao.HostDetailsDao;
+import com.cloud.network.BigSwitchVnsDeviceVO;
+import com.cloud.network.Network;
+import com.cloud.network.Network.Capability;
+import com.cloud.network.Network.Provider;
+import com.cloud.network.Network.Service;
+import com.cloud.network.NetworkModel;
+import com.cloud.network.NetworkVO;
+import com.cloud.network.Networks;
+import com.cloud.network.Networks.BroadcastDomainType;
+import com.cloud.network.PhysicalNetwork;
+import com.cloud.network.PhysicalNetworkServiceProvider;
+import com.cloud.network.PhysicalNetworkVO;
+import com.cloud.network.dao.BigSwitchVnsDao;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NetworkServiceMapDao;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
+import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
+import com.cloud.network.resource.BigSwitchVnsResource;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.resource.ResourceManager;
+import com.cloud.resource.ResourceState;
+import com.cloud.resource.ResourceStateAdapter;
+import com.cloud.resource.ServerResource;
+import com.cloud.resource.UnableDeleteHostException;
+import com.cloud.utils.component.AdapterBase;
+import com.cloud.utils.component.Inject;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineProfile;
+
+@Local(value = {NetworkElement.class, ConnectivityProvider.class})
+public class BigSwitchVnsElement extends AdapterBase implements
+ BigSwitchVnsElementService, ConnectivityProvider, ResourceStateAdapter {
+ private static final Logger s_logger = Logger.getLogger(BigSwitchVnsElement.class);
+
+ private static final Map> capabilities = setCapabilities();
+
+ @Inject
+ ResourceManager _resourceMgr;
+ @Inject
+ PhysicalNetworkDao _physicalNetworkDao;
+ @Inject
+ PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
+ @Inject
+ BigSwitchVnsDao _bigswitchVnsDao;
+ @Inject
+ HostDetailsDao _hostDetailsDao;
+ @Inject
+ HostDao _hostDao;
+ @Inject
+ AgentManager _agentMgr;
+ @Inject
+ NetworkDao _networkDao;
+ @Inject
+ NetworkModel _networkModel;
+ @Inject
+ ConfigurationManager _configMgr;
+ @Inject
+ NetworkServiceMapDao _ntwkSrvcDao;
+ @Inject
+ VlanDao _vlanDao;
+
+ @Override
+ public Map> getCapabilities() {
+ return capabilities;
+ }
+
+ @Override
+ public Provider getProvider() {
+ return VnsConstants.BigSwitchVns;
+ }
+
+ private boolean canHandle(Network network, Service service) {
+ s_logger.debug("Checking if BigSwitchVnsElement can handle service "
+ + service.getName() + " on network " + network.getDisplayText());
+ if (network.getBroadcastDomainType() != BroadcastDomainType.Lswitch) {
+ return false;
+ }
+
+ if (!_networkModel.isProviderForNetwork(getProvider(),
+ network.getId())) {
+ s_logger.debug("BigSwitchVnsElement is not a provider for network "
+ + network.getDisplayText());
+ return false;
+ }
+
+ if (!_ntwkSrvcDao.canProviderSupportServiceInNetwork(network.getId(),
+ service, VnsConstants.BigSwitchVns)) {
+ s_logger.debug("BigSwitchVnsElement can't provide the "
+ + service.getName() + " service on network "
+ + network.getDisplayText());
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean configure(String name, Map params)
+ throws ConfigurationException {
+ super.configure(name, params);
+ _resourceMgr.registerResourceStateAdapter(this.getClass()
+ .getSimpleName(), this);
+ return true;
+ }
+
+ @Override
+ public boolean implement(Network network, NetworkOffering offering,
+ DeployDestination dest, ReservationContext context)
+ throws ConcurrentOperationException, ResourceUnavailableException,
+ InsufficientCapacityException {
+ s_logger.debug("entering BigSwitchVnsElement implement function for network "
+ + network.getDisplayText()
+ + " (state "
+ + network.getState()
+ + ")");
+
+ return true;
+ }
+
+ @Override
+ public boolean prepare(Network network, NicProfile nic,
+ VirtualMachineProfile extends VirtualMachine> vm,
+ DeployDestination dest, ReservationContext context)
+ throws ConcurrentOperationException, ResourceUnavailableException,
+ InsufficientCapacityException {
+
+ if (!canHandle(network, Service.Connectivity)) {
+ return false;
+ }
+
+ if (network.getBroadcastUri() == null) {
+ s_logger.error("Nic has no broadcast Uri with the LSwitch Uuid");
+ return false;
+ }
+
+ String mac = nic.getMacAddress();
+ String tenantId = context.getDomain().getName() + "-" + context.getAccount().getAccountId();
+
+ List devices = _bigswitchVnsDao
+ .listByPhysicalNetwork(network.getPhysicalNetworkId());
+ if (devices.isEmpty()) {
+ s_logger.error("No BigSwitch Controller on physical network "
+ + network.getPhysicalNetworkId());
+ return false;
+ }
+ BigSwitchVnsDeviceVO bigswitchVnsDevice = devices.get(0);
+ HostVO bigswitchVnsHost = _hostDao.findById(bigswitchVnsDevice.getHostId());
+
+ CreateVnsPortCommand cmd = new CreateVnsPortCommand(
+ network.getBroadcastUri().getSchemeSpecificPart(),
+ vm.getUuid(),
+ tenantId,
+ nic.getName(),
+ mac);
+ CreateVnsPortAnswer answer = (CreateVnsPortAnswer) _agentMgr
+ .easySend(bigswitchVnsHost.getId(), cmd);
+
+ if (answer == null || !answer.getResult()) {
+ s_logger.error("CreatePortCommand failed");
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean release(Network network, NicProfile nic,
+ VirtualMachineProfile extends VirtualMachine> vm,
+ ReservationContext context) throws ConcurrentOperationException,
+ ResourceUnavailableException {
+
+ if (!canHandle(network, Service.Connectivity)) {
+ return false;
+ }
+
+ if (network.getBroadcastUri() == null) {
+ s_logger.error("Nic has no broadcast Uri with the LSwitch Uuid");
+ return false;
+ }
+
+ String tenantId = context.getDomain().getName() + "-" + context.getAccount().getAccountId();
+
+ List devices = _bigswitchVnsDao
+ .listByPhysicalNetwork(network.getPhysicalNetworkId());
+ if (devices.isEmpty()) {
+ s_logger.error("No BigSwitch Controller on physical network "
+ + network.getPhysicalNetworkId());
+ return false;
+ }
+ BigSwitchVnsDeviceVO bigswitchVnsDevice = devices.get(0);
+ HostVO bigswitchVnsHost = _hostDao.findById(bigswitchVnsDevice.getHostId());
+
+ DeleteVnsPortCommand cmd = new DeleteVnsPortCommand(
+ network.getBroadcastUri().getSchemeSpecificPart(),
+ vm.getUuid(),
+ tenantId);
+ DeleteVnsPortAnswer answer = (DeleteVnsPortAnswer) _agentMgr
+ .easySend(bigswitchVnsHost.getId(), cmd);
+
+ if (answer == null || !answer.getResult()) {
+ s_logger.error("DeletePortCommand failed");
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean shutdown(Network network, ReservationContext context,
+ boolean cleanup) throws ConcurrentOperationException,
+ ResourceUnavailableException {
+ if (!canHandle(network, Service.Connectivity)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean destroy(Network network, ReservationContext context)
+ throws ConcurrentOperationException, ResourceUnavailableException {
+ if (!canHandle(network, Service.Connectivity)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean isReady(PhysicalNetworkServiceProvider provider) {
+ return true;
+ }
+
+ @Override
+ public boolean shutdownProviderInstances(
+ PhysicalNetworkServiceProvider provider, ReservationContext context)
+ throws ConcurrentOperationException, ResourceUnavailableException {
+ // Nothing to do here.
+ return true;
+ }
+
+ @Override
+ public boolean canEnableIndividualServices() {
+ return true;
+ }
+
+ @Override
+ public boolean verifyServicesCombination(Set services) {
+ if (!services.contains(Service.Connectivity)) {
+ s_logger.warn("Unable to provide services without Connectivity service enabled for this element");
+ return false;
+ }
+ return true;
+ }
+
+ private static Map> setCapabilities() {
+ Map> capabilities = new HashMap>();
+
+ // L2 Support : SDN provisioning
+ capabilities.put(Service.Connectivity, null);
+
+ return capabilities;
+ }
+
+ @Override
+ @DB
+ public BigSwitchVnsDeviceVO addBigSwitchVnsDevice(AddBigSwitchVnsDeviceCmd cmd) {
+ ServerResource resource = new BigSwitchVnsResource();
+ String deviceName = VnsConstants.BigSwitchVns.getName();
+ NetworkDevice networkDevice = NetworkDevice
+ .getNetworkDevice(deviceName);
+ Long physicalNetworkId = cmd.getPhysicalNetworkId();
+ BigSwitchVnsDeviceVO bigswitchVnsDevice = null;
+
+ PhysicalNetworkVO physicalNetwork = _physicalNetworkDao
+ .findById(physicalNetworkId);
+ if (physicalNetwork == null) {
+ throw new InvalidParameterValueException(
+ "Could not find phyical network with ID: "
+ + physicalNetworkId);
+ }
+ long zoneId = physicalNetwork.getDataCenterId();
+
+ PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao
+ .findByServiceProvider(physicalNetwork.getId(),
+ networkDevice.getNetworkServiceProvder());
+ if (ntwkSvcProvider == null) {
+ throw new CloudRuntimeException("Network Service Provider: "
+ + networkDevice.getNetworkServiceProvder()
+ + " is not enabled in the physical network: "
+ + physicalNetworkId + "to add this device");
+ } else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
+ throw new CloudRuntimeException("Network Service Provider: "
+ + ntwkSvcProvider.getProviderName()
+ + " is in shutdown state in the physical network: "
+ + physicalNetworkId + "to add this device");
+ }
+
+ if (_bigswitchVnsDao.listByPhysicalNetwork(physicalNetworkId).size() != 0) {
+ throw new CloudRuntimeException(
+ "A BigSwitch controller device is already configured on this physical network");
+ }
+
+ Map params = new HashMap();
+ params.put("guid", UUID.randomUUID().toString());
+ params.put("zoneId", String.valueOf(physicalNetwork.getDataCenterId()));
+ params.put("physicalNetworkId", String.valueOf(physicalNetwork.getId()));
+ params.put("name", "BigSwitch Controller - " + cmd.getHost());
+ params.put("ip", cmd.getHost());
+ // FIXME What to do with multiple isolation types
+ params.put("transportzoneisotype",
+ physicalNetwork.getIsolationMethods().get(0).toLowerCase());
+
+ Map hostdetails = new HashMap();
+ hostdetails.putAll(params);
+
+ Transaction txn = Transaction.currentTxn();
+ try {
+ resource.configure(cmd.getHost(), hostdetails);
+
+ Host host = _resourceMgr.addHost(zoneId, resource,
+ Host.Type.L2Networking, params);
+ if (host != null) {
+ txn.start();
+
+ bigswitchVnsDevice = new BigSwitchVnsDeviceVO(host.getId(),
+ physicalNetworkId, ntwkSvcProvider.getProviderName(),
+ deviceName);
+ _bigswitchVnsDao.persist(bigswitchVnsDevice);
+
+ DetailVO detail = new DetailVO(host.getId(),
+ "bigswitchvnsdeviceid",
+ String.valueOf(bigswitchVnsDevice.getId()));
+ _hostDetailsDao.persist(detail);
+
+ txn.commit();
+ return bigswitchVnsDevice;
+ } else {
+ throw new CloudRuntimeException(
+ "Failed to add BigSwitch Vns Device due to internal error.");
+ }
+ } catch (ConfigurationException e) {
+ txn.rollback();
+ throw new CloudRuntimeException(e.getMessage());
+ }
+ }
+
+ @Override
+ public BigSwitchVnsDeviceResponse createBigSwitchVnsDeviceResponse(
+ BigSwitchVnsDeviceVO bigswitchVnsDeviceVO) {
+ HostVO bigswitchVnsHost = _hostDao.findById(bigswitchVnsDeviceVO.getHostId());
+ _hostDao.loadDetails(bigswitchVnsHost);
+
+ BigSwitchVnsDeviceResponse response = new BigSwitchVnsDeviceResponse();
+ response.setDeviceName(bigswitchVnsDeviceVO.getDeviceName());
+ PhysicalNetwork pnw = ApiDBUtils.findPhysicalNetworkById(bigswitchVnsDeviceVO.getPhysicalNetworkId());
+ if (pnw != null) {
+ response.setPhysicalNetworkId(pnw.getUuid());
+ }
+ response.setId(bigswitchVnsDeviceVO.getUuid());
+ response.setProviderName(bigswitchVnsDeviceVO.getProviderName());
+ response.setHostName(bigswitchVnsHost.getDetail("ip"));
+ response.setObjectName("bigswitchvnsdevice");
+ return response;
+ }
+
+ @Override
+ public boolean deleteBigSwitchVnsDevice(DeleteBigSwitchVnsDeviceCmd cmd) {
+ Long bigswitchVnsDeviceId = cmd.getBigSwitchVnsDeviceId();
+ BigSwitchVnsDeviceVO bigswitchVnsDevice = _bigswitchVnsDao
+ .findById(bigswitchVnsDeviceId);
+ if (bigswitchVnsDevice == null) {
+ throw new InvalidParameterValueException(
+ "Could not find a BigSwitch Controller with id " + bigswitchVnsDevice);
+ }
+
+ // Find the physical network we work for
+ Long physicalNetworkId = bigswitchVnsDevice.getPhysicalNetworkId();
+ PhysicalNetworkVO physicalNetwork = _physicalNetworkDao
+ .findById(physicalNetworkId);
+ if (physicalNetwork != null) {
+ List networkList = _networkDao
+ .listByPhysicalNetwork(physicalNetworkId);
+
+ // Networks with broadcast type lswitch are ours
+ for (NetworkVO network : networkList) {
+ if (network.getBroadcastDomainType() == Networks.BroadcastDomainType.Lswitch) {
+ if ((network.getState() != Network.State.Shutdown)
+ && (network.getState() != Network.State.Destroy)) {
+ throw new CloudRuntimeException(
+ "This BigSwitch Controller device can not be deleted as there are one or more " +
+ "logical networks provisioned by cloudstack.");
+ }
+ }
+ }
+ }
+
+ HostVO bigswitchHost = _hostDao.findById(bigswitchVnsDevice.getHostId());
+ Long hostId = bigswitchHost.getId();
+
+ bigswitchHost.setResourceState(ResourceState.Maintenance);
+ _hostDao.update(hostId, bigswitchHost);
+ _resourceMgr.deleteHost(hostId, false, false);
+
+ _bigswitchVnsDao.remove(bigswitchVnsDeviceId);
+ return true;
+ }
+
+ @Override
+ public List listBigSwitchVnsDevices(
+ ListBigSwitchVnsDevicesCmd cmd) {
+ Long physicalNetworkId = cmd.getPhysicalNetworkId();
+ Long bigswitchVnsDeviceId = cmd.getBigSwitchVnsDeviceId();
+ List responseList = new ArrayList();
+
+ if (physicalNetworkId == null && bigswitchVnsDeviceId == null) {
+ throw new InvalidParameterValueException(
+ "Either physical network Id or bigswitch device Id must be specified");
+ }
+
+ if (bigswitchVnsDeviceId != null) {
+ BigSwitchVnsDeviceVO bigswitchVnsDevice = _bigswitchVnsDao
+ .findById(bigswitchVnsDeviceId);
+ if (bigswitchVnsDevice == null) {
+ throw new InvalidParameterValueException(
+ "Could not find BigSwitch controller with id: "
+ + bigswitchVnsDevice);
+ }
+ responseList.add(bigswitchVnsDevice);
+ } else {
+ PhysicalNetworkVO physicalNetwork = _physicalNetworkDao
+ .findById(physicalNetworkId);
+ if (physicalNetwork == null) {
+ throw new InvalidParameterValueException(
+ "Could not find a physical network with id: "
+ + physicalNetworkId);
+ }
+ responseList = _bigswitchVnsDao
+ .listByPhysicalNetwork(physicalNetworkId);
+ }
+
+ return responseList;
+ }
+
+ @Override
+ public HostVO createHostVOForConnectedAgent(HostVO host,
+ StartupCommand[] cmd) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public HostVO createHostVOForDirectConnectAgent(HostVO host,
+ StartupCommand[] startup, ServerResource resource,
+ Map details, List hostTags) {
+ if (!(startup[0] instanceof StartupBigSwitchVnsCommand)) {
+ return null;
+ }
+ host.setType(Host.Type.L2Networking);
+ return host;
+ }
+
+ @Override
+ public DeleteHostAnswer deleteHost(HostVO host, boolean isForced,
+ boolean isForceDeleteStorage) throws UnableDeleteHostException {
+ if (!(host.getType() == Host.Type.L2Networking)) {
+ return null;
+ }
+ return new DeleteHostAnswer(true);
+ }
+
+ @Override
+ public List> getCommands() {
+ List> cmdList = new ArrayList>();
+ cmdList.add(AddBigSwitchVnsDeviceCmd.class);
+ cmdList.add(DeleteBigSwitchVnsDeviceCmd.class);
+ cmdList.add(ListBigSwitchVnsDevicesCmd.class);
+ return cmdList;
+ }
+
+}
diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/element/BigSwitchVnsElementService.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/element/BigSwitchVnsElementService.java
new file mode 100644
index 00000000000..915a2c2fa46
--- /dev/null
+++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/element/BigSwitchVnsElementService.java
@@ -0,0 +1,39 @@
+// 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.
+package com.cloud.network.element;
+
+import java.util.List;
+
+import com.cloud.api.commands.AddBigSwitchVnsDeviceCmd;
+import com.cloud.api.commands.DeleteBigSwitchVnsDeviceCmd;
+import com.cloud.api.commands.ListBigSwitchVnsDevicesCmd;
+import com.cloud.api.response.BigSwitchVnsDeviceResponse;
+import com.cloud.network.BigSwitchVnsDeviceVO;
+import com.cloud.utils.component.PluggableService;
+
+public interface BigSwitchVnsElementService extends PluggableService {
+
+ public BigSwitchVnsDeviceVO addBigSwitchVnsDevice(AddBigSwitchVnsDeviceCmd cmd);
+
+ public BigSwitchVnsDeviceResponse createBigSwitchVnsDeviceResponse(
+ BigSwitchVnsDeviceVO bigswitchDeviceVO);
+
+ boolean deleteBigSwitchVnsDevice(DeleteBigSwitchVnsDeviceCmd cmd);
+
+ List listBigSwitchVnsDevices(ListBigSwitchVnsDevicesCmd cmd);
+
+}
diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/guru/BigSwitchVnsGuestNetworkGuru.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/guru/BigSwitchVnsGuestNetworkGuru.java
new file mode 100644
index 00000000000..fe21163d9c8
--- /dev/null
+++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/guru/BigSwitchVnsGuestNetworkGuru.java
@@ -0,0 +1,261 @@
+/*
+ * 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.
+ */
+
+package com.cloud.network.guru;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.CreateVnsNetworkAnswer;
+import com.cloud.agent.api.CreateVnsNetworkCommand;
+import com.cloud.agent.api.DeleteVnsNetworkCommand;
+import com.cloud.dc.DataCenter;
+import com.cloud.dc.DataCenter.NetworkType;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.deploy.DeploymentPlan;
+import com.cloud.exception.InsufficientAddressCapacityException;
+import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.host.dao.HostDetailsDao;
+import com.cloud.network.BigSwitchVnsDeviceVO;
+import com.cloud.network.Network;
+import com.cloud.network.NetworkProfile;
+import com.cloud.network.NetworkVO;
+import com.cloud.network.Network.GuestType;
+import com.cloud.network.Network.State;
+import com.cloud.network.Networks.BroadcastDomainType;
+import com.cloud.network.PhysicalNetwork;
+import com.cloud.network.PhysicalNetwork.IsolationMethod;
+import com.cloud.network.PhysicalNetworkVO;
+import com.cloud.network.dao.BigSwitchVnsDao;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.resource.ResourceManager;
+import com.cloud.user.Account;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.utils.component.Inject;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineProfile;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import javax.ejb.Local;
+
+
+@Local(value = NetworkGuru.class)
+public class BigSwitchVnsGuestNetworkGuru extends GuestNetworkGuru {
+ private static final Logger s_logger = Logger.getLogger(BigSwitchVnsGuestNetworkGuru.class);
+
+ @Inject
+ DataCenterDao _zoneDao;
+ @Inject
+ PhysicalNetworkDao _physicalNetworkDao;
+ @Inject
+ AccountDao _accountDao;
+ @Inject
+ BigSwitchVnsDao _bigswitchVnsDao;
+ @Inject
+ HostDao _hostDao;
+ @Inject
+ ResourceManager _resourceMgr;
+ @Inject
+ AgentManager _agentMgr;
+ @Inject
+ HostDetailsDao _hostDetailsDao;
+
+ public BigSwitchVnsGuestNetworkGuru() {
+ super();
+ _isolationMethods = new IsolationMethod[] { IsolationMethod.VNS };
+ }
+
+ @Override
+ protected boolean canHandle(NetworkOffering offering, NetworkType networkType,
+ PhysicalNetwork physicalNetwork) {
+ if (networkType == NetworkType.Advanced
+ && isMyTrafficType(offering.getTrafficType())
+ && offering.getGuestType() == Network.GuestType.Isolated
+ && isMyIsolationMethod(physicalNetwork)) {
+ return true;
+ } else {
+ s_logger.trace("We only take care of Guest networks of type " + GuestType.Isolated +
+ " in zone of type " + NetworkType.Advanced);
+ return false;
+ }
+ }
+
+ @Override
+ public Network design(NetworkOffering offering, DeploymentPlan plan,
+ Network userSpecified, Account owner) {
+ // Check of the isolation type of the related physical network is VNS
+ PhysicalNetworkVO physnet = _physicalNetworkDao.findById(plan.getPhysicalNetworkId());
+ if (physnet == null ||
+ physnet.getIsolationMethods() == null ||
+ !physnet.getIsolationMethods().contains("VNS")) {
+ s_logger.debug("Refusing to design this network, the physical isolation type is not VNS");
+ return null;
+ }
+
+ List devices = _bigswitchVnsDao.listByPhysicalNetwork(physnet.getId());
+ if (devices.isEmpty()) {
+ s_logger.error("No BigSwitxh Controller on physical network " + physnet.getName());
+ return null;
+ }
+ s_logger.debug("BigSwitch Controller " + devices.get(0).getUuid() +
+ " found on physical network " + physnet.getId());
+
+ s_logger.debug("Physical isolation type is VNS, asking GuestNetworkGuru to design this network");
+ NetworkVO networkObject = (NetworkVO) super.design(offering, plan, userSpecified, owner);
+ if (networkObject == null) {
+ return null;
+ }
+ // Override the broadcast domain type
+ networkObject.setBroadcastDomainType(BroadcastDomainType.Lswitch);
+
+ return networkObject;
+ }
+
+ @Override
+ public Network implement(Network network, NetworkOffering offering,
+ DeployDestination dest, ReservationContext context)
+ throws InsufficientVirtualNetworkCapcityException {
+ assert (network.getState() == State.Implementing) : "Why are we implementing " + network;
+
+ long dcId = dest.getDataCenter().getId();
+
+ //get physical network id
+ long physicalNetworkId = _networkModel.findPhysicalNetworkId(dcId,
+ offering.getTags(),
+ offering.getTrafficType());
+
+ NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getMode(),
+ network.getBroadcastDomainType(), network.getNetworkOfferingId(), State.Allocated,
+ network.getDataCenterId(), physicalNetworkId);
+
+ if (network.getGateway() != null) {
+ implemented.setGateway(network.getGateway());
+ }
+
+ if (network.getCidr() != null) {
+ implemented.setCidr(network.getCidr());
+ }
+
+ String vnet = _dcDao.allocateVnet(dcId, physicalNetworkId,
+ network.getAccountId(), context.getReservationId());
+ if (vnet == null) {
+ throw new InsufficientVirtualNetworkCapcityException("Unable to allocate vnet as a " +
+ "part of network " + network + " implement ", DataCenter.class, dcId);
+ }
+ int vlan = Integer.parseInt(vnet);
+
+ // Name is either the given name or the uuid
+ String name = network.getName();
+ String networkUuid = implemented.getUuid();
+ if (name == null || name.isEmpty()) {
+ name = ((NetworkVO)network).getUuid();
+ }
+ if (name.length() > 64 ) {
+ name = name.substring(0, 63); // max length 64
+ }
+
+ String tenantId = context.getDomain().getName() + "-" + context.getAccount().getAccountId();
+ List devices = _bigswitchVnsDao.listByPhysicalNetwork(physicalNetworkId);
+ if (devices.isEmpty()) {
+ s_logger.error("No BigSwitch Controller on physical network " + physicalNetworkId);
+ return null;
+ }
+ BigSwitchVnsDeviceVO bigswitchVnsDevice = devices.get(0);
+ HostVO bigswitchVnsHost = _hostDao.findById(bigswitchVnsDevice.getHostId());
+ _hostDao.loadDetails(bigswitchVnsHost);
+
+ CreateVnsNetworkCommand cmd = new CreateVnsNetworkCommand(networkUuid, name, tenantId, vlan);
+ CreateVnsNetworkAnswer answer = (CreateVnsNetworkAnswer) _agentMgr.easySend(bigswitchVnsHost.getId(), cmd);
+
+ if (answer == null || !answer.getResult()) {
+ s_logger.error ("CreateNetworkCommand failed");
+ return null;
+ }
+
+ try {
+ implemented.setBroadcastUri(new URI("vns", cmd.getNetworkUuid(), null));
+ implemented.setBroadcastDomainType(BroadcastDomainType.Lswitch);
+ s_logger.info("Implemented OK, network " + networkUuid + " in tenant " +
+ tenantId + " linked to " + implemented.getBroadcastUri().toString());
+ } catch (URISyntaxException e) {
+ s_logger.error("Unable to store network id in broadcast uri, uuid = " + implemented.getUuid(), e);
+ }
+
+ return implemented;
+ }
+
+ @Override
+ public void reserve(NicProfile nic, Network network,
+ VirtualMachineProfile extends VirtualMachine> vm,
+ DeployDestination dest, ReservationContext context)
+ throws InsufficientVirtualNetworkCapcityException,
+ InsufficientAddressCapacityException {
+ // TODO Auto-generated method stub
+ super.reserve(nic, network, vm, dest, context);
+ }
+
+ @Override
+ public boolean release(NicProfile nic,
+ VirtualMachineProfile extends VirtualMachine> vm,
+ String reservationId) {
+ // TODO Auto-generated method stub
+ return super.release(nic, vm, reservationId);
+ }
+
+ @Override
+ public void shutdown(NetworkProfile profile, NetworkOffering offering) {
+ NetworkVO networkObject = _networkDao.findById(profile.getId());
+ if (networkObject.getBroadcastDomainType() != BroadcastDomainType.Lswitch ||
+ networkObject.getBroadcastUri() == null) {
+ s_logger.warn("BroadcastUri is empty or incorrect for guestnetwork " + networkObject.getDisplayText());
+ return;
+ }
+
+ List devices = _bigswitchVnsDao.listByPhysicalNetwork(networkObject.getPhysicalNetworkId());
+ if (devices.isEmpty()) {
+ s_logger.error("No BigSwitch Controller on physical network " + networkObject.getPhysicalNetworkId());
+ return;
+ }
+ BigSwitchVnsDeviceVO bigswitchVnsDevice = devices.get(0);
+ HostVO bigswitchVnsHost = _hostDao.findById(bigswitchVnsDevice.getHostId());
+
+ String tenantId = profile.getNetworkDomain() + "-" + profile.getAccountId();
+
+ DeleteVnsNetworkCommand cmd = new DeleteVnsNetworkCommand(tenantId,
+ networkObject.getBroadcastUri().getSchemeSpecificPart());
+ _agentMgr.easySend(bigswitchVnsHost.getId(), cmd);
+
+ super.shutdown(profile, offering);
+ }
+
+ @Override
+ public boolean trash(Network network, NetworkOffering offering,
+ Account owner) {
+ return super.trash(network, offering, owner);
+ }
+}
diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/resource/BigSwitchVnsResource.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/resource/BigSwitchVnsResource.java
new file mode 100644
index 00000000000..52c9ba7a2c2
--- /dev/null
+++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/resource/BigSwitchVnsResource.java
@@ -0,0 +1,322 @@
+// 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.
+package com.cloud.network.resource;
+
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.IAgentControl;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.CreateVnsNetworkAnswer;
+import com.cloud.agent.api.CreateVnsNetworkCommand;
+import com.cloud.agent.api.CreateVnsPortAnswer;
+import com.cloud.agent.api.CreateVnsPortCommand;
+import com.cloud.agent.api.DeleteVnsNetworkAnswer;
+import com.cloud.agent.api.DeleteVnsNetworkCommand;
+import com.cloud.agent.api.DeleteVnsPortAnswer;
+import com.cloud.agent.api.DeleteVnsPortCommand;
+import com.cloud.agent.api.MaintainAnswer;
+import com.cloud.agent.api.MaintainCommand;
+import com.cloud.agent.api.PingCommand;
+import com.cloud.agent.api.ReadyAnswer;
+import com.cloud.agent.api.ReadyCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupBigSwitchVnsCommand;
+import com.cloud.agent.api.UpdateVnsPortAnswer;
+import com.cloud.agent.api.UpdateVnsPortCommand;
+import com.cloud.host.Host;
+import com.cloud.host.Host.Type;
+import com.cloud.network.bigswitch.BigSwitchVnsApi;
+import com.cloud.network.bigswitch.BigSwitchVnsApiException;
+import com.cloud.network.bigswitch.ControlClusterStatus;
+import com.cloud.network.bigswitch.Attachment;
+import com.cloud.network.bigswitch.Network;
+import com.cloud.network.bigswitch.Port;
+import com.cloud.resource.ServerResource;
+
+public class BigSwitchVnsResource implements ServerResource {
+ private static final Logger s_logger = Logger.getLogger(BigSwitchVnsResource.class);
+
+ private String _name;
+ private String _guid;
+ private String _zoneId;
+ private int _numRetries;
+
+ private BigSwitchVnsApi _bigswitchVnsApi;
+
+ protected BigSwitchVnsApi createBigSwitchVnsApi() {
+ return new BigSwitchVnsApi();
+ }
+
+ @Override
+ public boolean configure(String name, Map params)
+ throws ConfigurationException {
+
+ _name = (String) params.get("name");
+ if (_name == null) {
+ throw new ConfigurationException("Unable to find name");
+ }
+
+ _guid = (String)params.get("guid");
+ if (_guid == null) {
+ throw new ConfigurationException("Unable to find the guid");
+ }
+
+ _zoneId = (String) params.get("zoneId");
+ if (_zoneId == null) {
+ throw new ConfigurationException("Unable to find zone");
+ }
+
+ _numRetries = 2;
+
+ String ip = (String) params.get("ip");
+ if (ip == null) {
+ throw new ConfigurationException("Unable to find IP");
+ }
+
+ _bigswitchVnsApi = createBigSwitchVnsApi();
+ _bigswitchVnsApi.setControllerAddress(ip);
+
+ return true;
+ }
+
+ @Override
+ public boolean start() {
+ return true;
+ }
+
+ @Override
+ public boolean stop() {
+ return true;
+ }
+
+ @Override
+ public String getName() {
+ return _name;
+ }
+
+ @Override
+ public Type getType() {
+ // Think up a better name for this Type?
+ return Host.Type.L2Networking;
+ }
+
+ @Override
+ public StartupCommand[] initialize() {
+ StartupBigSwitchVnsCommand sc = new StartupBigSwitchVnsCommand();
+ sc.setGuid(_guid);
+ sc.setName(_name);
+ sc.setDataCenter(_zoneId);
+ sc.setPod("");
+ sc.setPrivateIpAddress("");
+ sc.setStorageIpAddress("");
+ sc.setVersion("");
+ return new StartupCommand[] { sc };
+ }
+
+ @Override
+ public PingCommand getCurrentStatus(long id) {
+ try {
+ ControlClusterStatus ccs = _bigswitchVnsApi.getControlClusterStatus();
+ if (!ccs.getStatus()) {
+ s_logger.error("ControlCluster state is not ready: " + ccs.getStatus());
+ return null;
+ }
+ } catch (BigSwitchVnsApiException e) {
+ s_logger.error("getControlClusterStatus failed", e);
+ return null;
+ }
+ return new PingCommand(Host.Type.L2Networking, id);
+ }
+
+ @Override
+ public Answer executeRequest(Command cmd) {
+ return executeRequest(cmd, _numRetries);
+ }
+
+ public Answer executeRequest(Command cmd, int numRetries) {
+ if (cmd instanceof ReadyCommand) {
+ return executeRequest((ReadyCommand) cmd);
+ }
+ else if (cmd instanceof MaintainCommand) {
+ return executeRequest((MaintainCommand)cmd);
+ }
+ else if (cmd instanceof CreateVnsNetworkCommand) {
+ return executeRequest((CreateVnsNetworkCommand)cmd, numRetries);
+ }
+ else if (cmd instanceof DeleteVnsNetworkCommand) {
+ return executeRequest((DeleteVnsNetworkCommand) cmd, numRetries);
+ }
+ else if (cmd instanceof CreateVnsPortCommand) {
+ return executeRequest((CreateVnsPortCommand) cmd, numRetries);
+ }
+ else if (cmd instanceof DeleteVnsPortCommand) {
+ return executeRequest((DeleteVnsPortCommand) cmd, numRetries);
+ }
+ else if (cmd instanceof UpdateVnsPortCommand) {
+ return executeRequest((UpdateVnsPortCommand) cmd, numRetries);
+ }
+ s_logger.debug("Received unsupported command " + cmd.toString());
+ return Answer.createUnsupportedCommandAnswer(cmd);
+ }
+
+ @Override
+ public void disconnected() {
+ }
+
+ @Override
+ public IAgentControl getAgentControl() {
+ return null;
+ }
+
+ @Override
+ public void setAgentControl(IAgentControl agentControl) {
+ }
+
+ private Answer executeRequest(CreateVnsNetworkCommand cmd, int numRetries) {
+ Network network = new Network();
+ network.setTenant_id(cmd.getTenantUuid());
+ network.setUuid(cmd.getNetworkUuid());
+ network.setDisplay_name(truncate("vns-cloudstack-" + cmd.getName(), 64));
+ network.setVlan(cmd.getVlan());
+
+ try {
+ _bigswitchVnsApi.createNetwork(network);
+ return new CreateVnsNetworkAnswer(cmd, true, "VNS " + network.getUuid() + " created");
+ } catch (BigSwitchVnsApiException e) {
+ if (numRetries > 0) {
+ return retry(cmd, --numRetries);
+ }
+ else {
+ return new CreateVnsNetworkAnswer(cmd, e);
+ }
+ }
+
+ }
+
+ private Answer executeRequest(DeleteVnsNetworkCommand cmd, int numRetries) {
+ try {
+ _bigswitchVnsApi.deleteNetwork(cmd.get_tenantUuid(), cmd.getNetworkUuid());
+ return new DeleteVnsNetworkAnswer(cmd, true, "VNS " + cmd.getNetworkUuid() + " deleted");
+ } catch (BigSwitchVnsApiException e) {
+ if (numRetries > 0) {
+ return retry(cmd, --numRetries);
+ }
+ else {
+ return new DeleteVnsNetworkAnswer(cmd, e);
+ }
+ }
+ }
+
+ private Answer executeRequest(CreateVnsPortCommand cmd, int numRetries) {
+ Port port = new Port();
+ port.setId(cmd.getPortUuid());
+ port.setName(cmd.getPortName());
+ port.setTenant_id(cmd.getTenantUuid());
+
+ try {
+ _bigswitchVnsApi.createPort(cmd.getNetworkUuid(), port);
+ try {
+ Attachment attachment = new Attachment();
+ attachment.setId(cmd.getPortUuid());
+ attachment.setMac(cmd.getMac());
+ _bigswitchVnsApi.modifyPortAttachment(cmd.getTenantUuid(),
+ cmd.getNetworkUuid(), cmd.getPortUuid(), attachment);
+
+ } catch (BigSwitchVnsApiException ex) {
+ s_logger.warn("modifyPortAttachment failed after switchport was created, removing switchport");
+ _bigswitchVnsApi.deletePort(cmd.getTenantUuid(), cmd.getNetworkUuid(), cmd.getPortUuid());
+ throw (ex); // Rethrow the original exception
+ }
+ return new CreateVnsPortAnswer(cmd, true, "network port " + cmd.getPortUuid() + " created");
+ } catch (BigSwitchVnsApiException e) {
+ if (numRetries > 0) {
+ return retry(cmd, --numRetries);
+ }
+ else {
+ return new CreateVnsPortAnswer(cmd, e);
+ }
+ }
+ }
+
+ private Answer executeRequest(DeleteVnsPortCommand cmd, int numRetries) {
+ try {
+ _bigswitchVnsApi.deletePortAttachment(cmd.getTenantUuid(), cmd.getNetworkUuid(), cmd.getPortUuid());
+ try {
+ _bigswitchVnsApi.deletePort(cmd.getTenantUuid(), cmd.getNetworkUuid(), cmd.getPortUuid());
+ } catch (BigSwitchVnsApiException ex) {
+ s_logger.warn("deletePort failed after portAttachment was removed");
+ throw (ex); // Rethrow the original exception
+ }
+ return new DeleteVnsPortAnswer(cmd, true, "network port " + cmd.getPortUuid() + " deleted");
+ } catch (BigSwitchVnsApiException e) {
+ if (numRetries > 0) {
+ return retry(cmd, --numRetries);
+ }
+ else {
+ return new DeleteVnsPortAnswer(cmd, e);
+ }
+ }
+ }
+
+ private Answer executeRequest(UpdateVnsPortCommand cmd, int numRetries) {
+ Port port = new Port();
+ port.setId(cmd.getPortUuid());
+ port.setName(cmd.getPortName());
+ port.setTenant_id(cmd.getTenantUuid());
+
+ try {
+ _bigswitchVnsApi.modifyPort(cmd.getNetworkUuid(), port);
+ return new UpdateVnsPortAnswer(cmd, true, "Network Port " + cmd.getPortUuid() + " updated");
+ } catch (BigSwitchVnsApiException e) {
+ if (numRetries > 0) {
+ return retry(cmd, --numRetries);
+ }
+ else {
+ return new UpdateVnsPortAnswer(cmd, e);
+ }
+ }
+
+ }
+
+ private Answer executeRequest(ReadyCommand cmd) {
+ return new ReadyAnswer(cmd);
+ }
+
+ private Answer executeRequest(MaintainCommand cmd) {
+ return new MaintainAnswer(cmd);
+ }
+
+ private Answer retry(Command cmd, int numRetries) {
+ s_logger.warn("Retrying " + cmd.getClass().getSimpleName() + ". Number of retries remaining: " + numRetries);
+ return executeRequest(cmd, numRetries);
+ }
+
+ private String truncate(String string, int length) {
+ if (string.length() <= length) {
+ return string;
+ }
+ else {
+ return string.substring(0, length);
+ }
+ }
+
+}
diff --git a/plugins/network-elements/bigswitch-vns/test/com/cloud/network/bigswitch/BigSwitchApiTest.java b/plugins/network-elements/bigswitch-vns/test/com/cloud/network/bigswitch/BigSwitchApiTest.java
new file mode 100644
index 00000000000..cab06ba821f
--- /dev/null
+++ b/plugins/network-elements/bigswitch-vns/test/com/cloud/network/bigswitch/BigSwitchApiTest.java
@@ -0,0 +1,228 @@
+// 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.
+package com.cloud.network.bigswitch;
+
+import static org.mockito.Mockito.*;
+
+import java.io.IOException;
+import java.util.Collections;
+
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.methods.DeleteMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.PutMethod;
+import org.apache.commons.httpclient.params.HttpClientParams;
+import org.apache.http.HttpStatus;
+import org.junit.Before;
+import org.junit.Test;
+
+public class BigSwitchApiTest {
+ BigSwitchVnsApi _api;
+ HttpClient _client = mock(HttpClient.class);
+ HttpMethod _method;
+
+ @Before
+ public void setUp() {
+ HttpClientParams hmp = mock(HttpClientParams.class);
+ when (_client.getParams()).thenReturn(hmp);
+ _api = new BigSwitchVnsApi() {
+ @Override
+ protected HttpClient createHttpClient() {
+ return _client;
+ }
+
+ @Override
+ protected HttpMethod createMethod(String type, String uri, int port) {
+ return _method;
+ }
+ };
+ }
+
+ @Test (expected=BigSwitchVnsApiException.class)
+ public void testExecuteUpdateObjectWithoutHostname() throws BigSwitchVnsApiException {
+ _api.setControllerAddress(null);
+ _api.executeUpdateObject(new String(), "/", Collections. emptyMap());
+ }
+
+ @Test (expected=BigSwitchVnsApiException.class)
+ public void testExecuteCreateObjectWithoutHostname() throws BigSwitchVnsApiException {
+ _api.setControllerAddress(null);
+ _api.executeCreateObject(new String(), String.class, "/", Collections. emptyMap());
+ }
+
+ @Test (expected=BigSwitchVnsApiException.class)
+ public void testExecuteDeleteObjectWithoutHostname() throws BigSwitchVnsApiException {
+ _api.setControllerAddress(null);
+ _api.executeDeleteObject("/");
+ }
+
+ @Test
+ public void executeMethodTest() throws BigSwitchVnsApiException {
+ GetMethod gm = mock(GetMethod.class);
+
+ when(gm.getStatusCode()).thenReturn(HttpStatus.SC_OK);
+ _api.executeMethod(gm);
+ verify(gm, times(1)).getStatusCode();
+ }
+
+ /* Bit of a roundabout way to ensure that login is called after an un authorized result
+ * It not possible to properly mock login()
+ */
+ @Test (expected=BigSwitchVnsApiException.class)
+ public void executeMethodTestWithLogin() throws BigSwitchVnsApiException, HttpException, IOException {
+ GetMethod gm = mock(GetMethod.class);
+ when(_client.executeMethod((HttpMethod)any())).thenThrow(new HttpException());
+ when(gm.getStatusCode()).thenReturn(HttpStatus.SC_UNAUTHORIZED).thenReturn(HttpStatus.SC_UNAUTHORIZED);
+ _api.executeMethod(gm);
+ verify(gm, times(1)).getStatusCode();
+ }
+
+ @Test
+ public void testExecuteCreateObject() throws BigSwitchVnsApiException, IOException {
+ _api.setControllerAddress("10.10.0.10");
+ Network network = new Network();
+ _method = mock(PostMethod.class);
+ when(_method.getStatusCode()).thenReturn(HttpStatus.SC_OK);
+ _api.executeCreateObject(network, Network.class, "/", Collections. emptyMap());
+ verify(_method, times(1)).releaseConnection();
+
+ }
+
+ @Test (expected=BigSwitchVnsApiException.class)
+ public void testExecuteCreateObjectFailure() throws BigSwitchVnsApiException, IOException {
+ _api.setControllerAddress("10.10.0.10");
+ Network network = new Network();
+ _method = mock(PostMethod.class);
+ when(_method.getStatusCode()).thenReturn(HttpStatus.SC_INTERNAL_SERVER_ERROR);
+ Header header = mock(Header.class);
+ when(header.getValue()).thenReturn("text/html");
+ when(_method.getResponseHeader("Content-Type")).thenReturn(header);
+ when(_method.getResponseBodyAsString()).thenReturn("Off to timbuktu, won't be back later.");
+ when(_method.isRequestSent()).thenReturn(true);
+ try {
+ _api.executeCreateObject(network, Network.class, "/", Collections. emptyMap());
+ } finally {
+ verify(_method, times(1)).releaseConnection();
+ }
+ }
+
+ @Test (expected=BigSwitchVnsApiException.class)
+ public void testExecuteCreateObjectException() throws BigSwitchVnsApiException, IOException {
+ _api.setControllerAddress("10.10.0.10");
+ Network network = new Network();
+ when(_client.executeMethod((HttpMethod) any())).thenThrow(new HttpException());
+ _method = mock(PostMethod.class);
+ when(_method.getStatusCode()).thenReturn(HttpStatus.SC_INTERNAL_SERVER_ERROR);
+ Header header = mock(Header.class);
+ when(header.getValue()).thenReturn("text/html");
+ when(_method.getResponseHeader("Content-Type")).thenReturn(header);
+ when(_method.getResponseBodyAsString()).thenReturn("Off to timbuktu, won't be back later.");
+ try {
+ _api.executeCreateObject(network, Network.class, "/", Collections. emptyMap());
+ } finally {
+ verify(_method, times(1)).releaseConnection();
+ }
+ }
+
+ @Test
+ public void testExecuteUpdateObject() throws BigSwitchVnsApiException, IOException {
+ _api.setControllerAddress("10.10.0.10");
+ Network network = new Network();
+ _method = mock(PutMethod.class);
+ when(_method.getStatusCode()).thenReturn(HttpStatus.SC_OK);
+ _api.executeUpdateObject(network, "/", Collections. emptyMap());
+ verify(_method, times(1)).releaseConnection();
+ verify(_client, times(1)).executeMethod(_method);
+ }
+
+ @Test (expected=BigSwitchVnsApiException.class)
+ public void testExecuteUpdateObjectFailure() throws BigSwitchVnsApiException, IOException {
+ _api.setControllerAddress("10.10.0.10");
+ Network network = new Network();
+ _method = mock(PutMethod.class);
+ when(_method.getStatusCode()).thenReturn(HttpStatus.SC_INTERNAL_SERVER_ERROR);
+ Header header = mock(Header.class);
+ when(header.getValue()).thenReturn("text/html");
+ when(_method.getResponseHeader("Content-Type")).thenReturn(header);
+ when(_method.getResponseBodyAsString()).thenReturn("Off to timbuktu, won't be back later.");
+ when(_method.isRequestSent()).thenReturn(true);
+ try {
+ _api.executeUpdateObject(network, "/", Collections. emptyMap());
+ } finally {
+ verify(_method, times(1)).releaseConnection();
+ }
+ }
+
+ @Test (expected=BigSwitchVnsApiException.class)
+ public void testExecuteUpdateObjectException() throws BigSwitchVnsApiException, IOException {
+ _api.setControllerAddress("10.10.0.10");
+ Network network = new Network();
+ _method = mock(PutMethod.class);
+ when(_method.getStatusCode()).thenReturn(HttpStatus.SC_OK);
+ when(_client.executeMethod((HttpMethod) any())).thenThrow(new IOException());
+ try {
+ _api.executeUpdateObject(network, "/", Collections. emptyMap());
+ } finally {
+ verify(_method, times(1)).releaseConnection();
+ }
+ }
+
+ @Test
+ public void testExecuteDeleteObject() throws BigSwitchVnsApiException, IOException {
+ _api.setControllerAddress("10.10.0.10");
+ _method = mock(DeleteMethod.class);
+ when(_method.getStatusCode()).thenReturn(HttpStatus.SC_OK);
+ _api.executeDeleteObject("/");
+ verify(_method, times(1)).releaseConnection();
+ verify(_client, times(1)).executeMethod(_method);
+ }
+
+ @Test (expected=BigSwitchVnsApiException.class)
+ public void testExecuteDeleteObjectFailure() throws BigSwitchVnsApiException, IOException {
+ _api.setControllerAddress("10.10.0.10");
+ _method = mock(DeleteMethod.class);
+ when(_method.getStatusCode()).thenReturn(HttpStatus.SC_INTERNAL_SERVER_ERROR);
+ Header header = mock(Header.class);
+ when(header.getValue()).thenReturn("text/html");
+ when(_method.getResponseHeader("Content-Type")).thenReturn(header);
+ when(_method.getResponseBodyAsString()).thenReturn("Off to timbuktu, won't be back later.");
+ when(_method.isRequestSent()).thenReturn(true);
+ try {
+ _api.executeDeleteObject("/");
+ } finally {
+ verify(_method, times(1)).releaseConnection();
+ }
+ }
+
+ @Test (expected=BigSwitchVnsApiException.class)
+ public void testExecuteDeleteObjectException() throws BigSwitchVnsApiException, IOException {
+ _api.setControllerAddress("10.10.0.10");
+ _method = mock(DeleteMethod.class);
+ when(_method.getStatusCode()).thenReturn(HttpStatus.SC_OK);
+ when(_client.executeMethod((HttpMethod) any())).thenThrow(new HttpException());
+ try {
+ _api.executeDeleteObject("/");
+ } finally {
+ verify(_method, times(1)).releaseConnection();
+ }
+ }
+
+}
diff --git a/plugins/network-elements/bigswitch-vns/test/com/cloud/network/resource/BigSwitchVnsResourceTest.java b/plugins/network-elements/bigswitch-vns/test/com/cloud/network/resource/BigSwitchVnsResourceTest.java
new file mode 100644
index 00000000000..514385feaa5
--- /dev/null
+++ b/plugins/network-elements/bigswitch-vns/test/com/cloud/network/resource/BigSwitchVnsResourceTest.java
@@ -0,0 +1,254 @@
+// 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.
+package com.cloud.network.resource;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.cloud.agent.api.CreateVnsNetworkAnswer;
+import com.cloud.agent.api.CreateVnsNetworkCommand;
+import com.cloud.agent.api.CreateVnsPortAnswer;
+import com.cloud.agent.api.CreateVnsPortCommand;
+import com.cloud.agent.api.DeleteVnsNetworkAnswer;
+import com.cloud.agent.api.DeleteVnsNetworkCommand;
+import com.cloud.agent.api.DeleteVnsPortAnswer;
+import com.cloud.agent.api.DeleteVnsPortCommand;
+import com.cloud.agent.api.PingCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.UpdateVnsPortAnswer;
+import com.cloud.agent.api.UpdateVnsPortCommand;
+import com.cloud.host.Host;
+import com.cloud.network.bigswitch.Attachment;
+import com.cloud.network.bigswitch.ControlClusterStatus;
+import com.cloud.network.bigswitch.Network;
+import com.cloud.network.bigswitch.Port;
+import com.cloud.network.bigswitch.BigSwitchVnsApi;
+import com.cloud.network.bigswitch.BigSwitchVnsApiException;
+
+public class BigSwitchVnsResourceTest {
+ BigSwitchVnsApi _bigswitchVnsApi = mock(BigSwitchVnsApi.class);
+ BigSwitchVnsResource _resource;
+ Map _parameters;
+
+ @Before
+ public void setUp() throws ConfigurationException {
+ _resource = new BigSwitchVnsResource() {
+ protected BigSwitchVnsApi createBigSwitchVnsApi() {
+ return _bigswitchVnsApi;
+ }
+ };
+
+ _parameters = new HashMap();
+ _parameters.put("name","bigswitchvnstestdevice");
+ _parameters.put("ip","127.0.0.1");
+ _parameters.put("guid", "aaaaa-bbbbb-ccccc");
+ _parameters.put("zoneId", "blublub");
+ }
+
+ @Test (expected=ConfigurationException.class)
+ public void resourceConfigureFailure() throws ConfigurationException {
+ _resource.configure("BigSwitchVnsResource", Collections.emptyMap());
+ }
+
+ @Test
+ public void resourceConfigure() throws ConfigurationException {
+ _resource.configure("BigSwitchVnsResource", _parameters);
+
+ verify(_bigswitchVnsApi).setControllerAddress("127.0.0.1");
+
+ assertTrue("bigswitchvnstestdevice".equals(_resource.getName()));
+
+ /* Pretty lame test, but here to assure this plugin fails
+ * if the type name ever changes from L2Networking
+ */
+ assertTrue(_resource.getType() == Host.Type.L2Networking);
+ }
+
+ @Test
+ public void testInitialization() throws ConfigurationException {
+ _resource.configure("BigSwitchVnsResource", _parameters);
+
+ StartupCommand[] sc = _resource.initialize();
+ assertTrue(sc.length ==1);
+ assertTrue("aaaaa-bbbbb-ccccc".equals(sc[0].getGuid()));
+ assertTrue("bigswitchvnstestdevice".equals(sc[0].getName()));
+ assertTrue("blublub".equals(sc[0].getDataCenter()));
+ }
+
+ @Test
+ public void testPingCommandStatusOk() throws ConfigurationException, BigSwitchVnsApiException {
+ _resource.configure("BigSwitchVnsResource", _parameters);
+
+ ControlClusterStatus ccs = mock(ControlClusterStatus.class);
+ when(ccs.getStatus()).thenReturn(true);
+ when(_bigswitchVnsApi.getControlClusterStatus()).thenReturn(ccs);
+
+ PingCommand ping = _resource.getCurrentStatus(42);
+ assertTrue(ping != null);
+ assertTrue(ping.getHostId() == 42);
+ assertTrue(ping.getHostType() == Host.Type.L2Networking);
+ }
+
+ @Test
+ public void testPingCommandStatusFail() throws ConfigurationException, BigSwitchVnsApiException {
+ _resource.configure("BigSwitchVnsResource", _parameters);
+
+ ControlClusterStatus ccs = mock(ControlClusterStatus.class);
+ when(ccs.getStatus()).thenReturn(false);
+ when(_bigswitchVnsApi.getControlClusterStatus()).thenReturn(ccs);
+
+ PingCommand ping = _resource.getCurrentStatus(42);
+ assertTrue(ping == null);
+ }
+
+ @Test
+ public void testPingCommandStatusApiException() throws ConfigurationException, BigSwitchVnsApiException {
+ _resource.configure("BigSwitchVnsResource", _parameters);
+
+ ControlClusterStatus ccs = mock(ControlClusterStatus.class);
+ when(ccs.getStatus()).thenReturn(false);
+ when(_bigswitchVnsApi.getControlClusterStatus()).thenThrow(new BigSwitchVnsApiException());
+
+ PingCommand ping = _resource.getCurrentStatus(42);
+ assertTrue(ping == null);
+ }
+
+ @Test
+ public void testRetries() throws ConfigurationException, BigSwitchVnsApiException {
+ _resource.configure("BigSwitchVnsResource", _parameters);
+
+ Network network = mock(Network.class);
+ when(network.getUuid()).thenReturn("cccc").thenReturn("cccc");
+
+ CreateVnsNetworkCommand cntkc = new CreateVnsNetworkCommand((String)_parameters.get("guid"), "networkName", "tenantid", 1);
+ CreateVnsNetworkAnswer cntka = (CreateVnsNetworkAnswer) _resource.executeRequest(cntkc);
+ assertTrue(cntka.getResult());
+ }
+
+ @Test
+ public void testCreateNetwork() throws ConfigurationException, BigSwitchVnsApiException {
+ _resource.configure("BigSwitchVnsResource", _parameters);
+
+ Network network = mock(Network.class);
+ when(network.getUuid()).thenReturn("cccc").thenReturn("cccc");
+
+ CreateVnsNetworkCommand cntkc = new CreateVnsNetworkCommand((String)_parameters.get("guid"), "networkName", "tenantid", 1);
+ CreateVnsNetworkAnswer cntka = (CreateVnsNetworkAnswer) _resource.executeRequest(cntkc);
+ assertTrue(cntka.getResult());
+ }
+
+ @Test
+ public void testCreateNetworkApiException() throws ConfigurationException, BigSwitchVnsApiException {
+ _resource.configure("BigSwitchVnsResource", _parameters);
+
+ Network network = mock(Network.class);
+ when(network.getUuid()).thenReturn("cccc").thenReturn("cccc");
+ doThrow(new BigSwitchVnsApiException()).when(_bigswitchVnsApi).createNetwork((Network)any());
+
+ CreateVnsNetworkCommand cntkc = new CreateVnsNetworkCommand((String)_parameters.get("guid"), "networkName", "tenantid", 1);
+ CreateVnsNetworkAnswer cntka = (CreateVnsNetworkAnswer) _resource.executeRequest(cntkc);
+ assertFalse(cntka.getResult());
+ }
+
+ @Test
+ public void testDeleteNetwork() throws ConfigurationException, BigSwitchVnsApiException {
+ _resource.configure("BigSwitchVnsResource", _parameters);
+
+ DeleteVnsNetworkCommand dntkc = new DeleteVnsNetworkCommand("tenantid", "networkid");
+ DeleteVnsNetworkAnswer dntka = (DeleteVnsNetworkAnswer) _resource.executeRequest(dntkc);
+ assertTrue(dntka.getResult());
+ }
+
+ @Test
+ public void testDeleteNetworkApiException() throws ConfigurationException, BigSwitchVnsApiException {
+ _resource.configure("BigSwitchVnsResource", _parameters);
+
+ doThrow(new BigSwitchVnsApiException()).when(_bigswitchVnsApi).deleteNetwork((String)any(), (String)any());
+
+ DeleteVnsNetworkCommand dntkc = new DeleteVnsNetworkCommand("tenantid", "networkid");
+ DeleteVnsNetworkAnswer dntka = (DeleteVnsNetworkAnswer) _resource.executeRequest(dntkc);
+ assertFalse(dntka.getResult());
+ }
+
+ @Test
+ public void testCreatePort() throws ConfigurationException, BigSwitchVnsApiException {
+ _resource.configure("BigSwitchVnsResource", _parameters);
+
+ Port networkp = mock(Port.class);
+ when(networkp.getId()).thenReturn("eeee");
+
+ CreateVnsPortCommand cntkc = new CreateVnsPortCommand("networkid", "portid", "tenantid", "portname", "aa:bb:cc:dd:ee:ff");
+ CreateVnsPortAnswer cntka = (CreateVnsPortAnswer) _resource.executeRequest(cntkc);
+ assertTrue(cntka.getResult());
+ }
+
+ @Test
+ public void testCreatePortApiExceptionInCreate() throws ConfigurationException, BigSwitchVnsApiException {
+ _resource.configure("BigSwitchVnsResource", _parameters);
+
+ Port networkp = mock(Port.class);
+ when(networkp.getId()).thenReturn("eeee");
+ doThrow(new BigSwitchVnsApiException()).when(_bigswitchVnsApi).createPort((String)any(), (Port)any());
+
+ CreateVnsPortCommand cntkc = new CreateVnsPortCommand("networkid", "portid", "tenantid", "portname", "aa:bb:cc:dd:ee:ff");
+ CreateVnsPortAnswer cntka = (CreateVnsPortAnswer) _resource.executeRequest(cntkc);
+ assertFalse(cntka.getResult());
+ }
+
+ @Test
+ public void testCreatePortApiExceptionInModify() throws ConfigurationException, BigSwitchVnsApiException {
+ _resource.configure("BigSwitchVnsResource", _parameters);
+
+ Port networkp = mock(Port.class);
+ when(networkp.getId()).thenReturn("eeee");
+ doThrow(new BigSwitchVnsApiException()).when(_bigswitchVnsApi).modifyPortAttachment((String)any(), (String)any(), (String)any(), (Attachment)any());
+
+ CreateVnsPortCommand cntkc = new CreateVnsPortCommand("networkid", "portid", "tenantid", "portname", "aa:bb:cc:dd:ee:ff");
+ CreateVnsPortAnswer cntka = (CreateVnsPortAnswer) _resource.executeRequest(cntkc);
+ assertFalse(cntka.getResult());
+ verify(_bigswitchVnsApi, atLeastOnce()).deletePort((String) any(), (String) any(), (String) any());
+ }
+
+ @Test
+ public void testDeletePortException() throws ConfigurationException, BigSwitchVnsApiException {
+ _resource.configure("BigSwitchVnsResource", _parameters);
+
+ doThrow(new BigSwitchVnsApiException()).when(_bigswitchVnsApi).deletePort((String) any(), (String) any(), (String) any());
+ DeleteVnsPortAnswer dntkpa = (DeleteVnsPortAnswer) _resource.executeRequest(new DeleteVnsPortCommand("networkId",
+ "portid", "tenantid"));
+ assertFalse(dntkpa.getResult());
+ }
+
+ @Test
+ public void testUpdatePortException() throws ConfigurationException, BigSwitchVnsApiException {
+ _resource.configure("BigSwitchVnsResource", _parameters);
+
+ doThrow(new BigSwitchVnsApiException()).when(_bigswitchVnsApi).modifyPort((String) any(), (Port)any());
+ UpdateVnsPortAnswer dntkpa = (UpdateVnsPortAnswer) _resource.executeRequest(
+ new UpdateVnsPortCommand("networkId","portId","tenantId","portname"));
+ assertFalse(dntkpa.getResult());
+ }
+}
diff --git a/plugins/pom.xml b/plugins/pom.xml
index f91c6eed58b..198a632972b 100644
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -47,6 +47,7 @@
network-elements/elastic-loadbalancer
network-elements/ovs
network-elements/nicira-nvp
+ network-elements/bigswitch-vns
storage-allocators/random
user-authenticators/ldap
user-authenticators/md5
diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql
index ad19e0fdbdc..0a57bfd1e5b 100755
--- a/setup/db/create-schema.sql
+++ b/setup/db/create-schema.sql
@@ -150,6 +150,7 @@ DROP TABLE IF EXISTS `cloud`,`nicira_nvp_nic_map`;
DROP TABLE IF EXISTS `cloud`,`s3`;
DROP TABLE IF EXISTS `cloud`,`template_s3_ref`;
DROP TABLE IF EXISTS `cloud`,`nicira_nvp_router_map`;
+DROP TABLE IF EXISTS `cloud`,`external_bigswitch_vns_devices`;
DROP TABLE IF EXISTS `cloud`.`autoscale_vmgroup_policy_map`;
DROP TABLE IF EXISTS `cloud`.`autoscale_policy_condition_map`;
DROP TABLE IF EXISTS `cloud`.`autoscale_vmgroups`;
@@ -2442,6 +2443,18 @@ CREATE TABLE `cloud`.`nicira_nvp_router_map` (
CONSTRAINT `fk_nicira_nvp_router_map__network_id` FOREIGN KEY (`network_id`) REFERENCES `networks`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+CREATE TABLE `cloud`.`external_bigswitch_vns_devices` (
+ `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
+ `uuid` varchar(255) UNIQUE,
+ `physical_network_id` bigint unsigned NOT NULL COMMENT 'id of the physical network in to which bigswitch vns device is added',
+ `provider_name` varchar(255) NOT NULL COMMENT 'Service Provider name corresponding to this bigswitch vns device',
+ `device_name` varchar(255) NOT NULL COMMENT 'name of the bigswitch vns device',
+ `host_id` bigint unsigned NOT NULL COMMENT 'host id coresponding to the external bigswitch vns device',
+ PRIMARY KEY (`id`),
+ CONSTRAINT `fk_external_bigswitch_vns_devices__host_id` FOREIGN KEY (`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE,
+ CONSTRAINT `fk_external_bigswitch_vns_devices__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
CREATE TABLE `cloud`.`counter` (
`id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT COMMENT 'id',
`uuid` varchar(40),
diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py
index b6bc8f24d95..2fd855d75ad 100644
--- a/tools/apidoc/gen_toc.py
+++ b/tools/apidoc/gen_toc.py
@@ -126,6 +126,7 @@ known_categories = {
'StaticRoute': 'VPC',
'Tags': 'Resource tags',
'NiciraNvpDevice': 'Nicira NVP',
+ 'BigSwitchVnsDevice': 'BigSwitch VNS',
'AutoScale': 'AutoScale',
'Counter': 'AutoScale',
'Condition': 'AutoScale',
diff --git a/ui/scripts/ui-custom/zoneWizard.js b/ui/scripts/ui-custom/zoneWizard.js
index ef606e949cb..47fa3857f9a 100644
--- a/ui/scripts/ui-custom/zoneWizard.js
+++ b/ui/scripts/ui-custom/zoneWizard.js
@@ -623,7 +623,10 @@
}).html('GRE'),
$('