From 736b236eaffc8a0252396e7ad2a5ba0ad6a909b0 Mon Sep 17 00:00:00 2001 From: Kanzhe Jiang Date: Fri, 1 Feb 2013 12:38:17 +0530 Subject: [PATCH] bigswitch controller support Reviewed-by: Chiradeep Vittal Signed-off-by: Murali Reddy --- .../com/cloud/network/PhysicalNetwork.java | 3 +- client/pom.xml | 5 + client/tomcatconf/commands.properties.in | 6 + client/tomcatconf/components.xml.in | 5 + cloud.spec | 1 + debian/cloud-server.install | 1 + docs/en-US/Release_Notes.xml | 9 + .../network-elements/bigswitch-vns/pom.xml | 29 + .../agent/api/CreateVnsNetworkAnswer.java | 28 + .../agent/api/CreateVnsNetworkCommand.java | 52 ++ .../cloud/agent/api/CreateVnsPortAnswer.java | 30 + .../cloud/agent/api/CreateVnsPortCommand.java | 65 +++ .../agent/api/DeleteVnsNetworkAnswer.java | 30 + .../agent/api/DeleteVnsNetworkCommand.java | 41 ++ .../cloud/agent/api/DeleteVnsPortAnswer.java | 30 + .../cloud/agent/api/DeleteVnsPortCommand.java | 48 ++ .../agent/api/StartupBigSwitchVnsCommand.java | 27 + .../cloud/agent/api/UpdateVnsPortAnswer.java | 30 + .../cloud/agent/api/UpdateVnsPortCommand.java | 58 ++ .../commands/AddBigSwitchVnsDeviceCmd.java | 110 ++++ .../commands/DeleteBigSwitchVnsDeviceCmd.java | 99 ++++ .../commands/ListBigSwitchVnsDevicesCmd.java | 109 ++++ .../com/cloud/api/commands/VnsConstants.java | 19 + .../response/BigSwitchVnsDeviceResponse.java | 63 ++ .../cloud/network/BigSwitchVnsDeviceVO.java | 94 +++ .../cloud/network/bigswitch/Attachment.java | 38 ++ .../network/bigswitch/BigSwitchVnsApi.java | 330 +++++++++++ .../bigswitch/BigSwitchVnsApiException.java | 39 ++ .../bigswitch/ControlClusterStatus.java | 25 + .../com/cloud/network/bigswitch/Network.java | 74 +++ .../src/com/cloud/network/bigswitch/Port.java | 56 ++ .../cloud/network/dao/BigSwitchVnsDao.java | 32 ++ .../network/dao/BigSwitchVnsDaoImpl.java | 48 ++ .../network/element/BigSwitchVnsElement.java | 543 ++++++++++++++++++ .../element/BigSwitchVnsElementService.java | 39 ++ .../guru/BigSwitchVnsGuestNetworkGuru.java | 261 +++++++++ .../resource/BigSwitchVnsResource.java | 322 +++++++++++ .../network/bigswitch/BigSwitchApiTest.java | 228 ++++++++ .../resource/BigSwitchVnsResourceTest.java | 254 ++++++++ plugins/pom.xml | 1 + setup/db/create-schema.sql | 13 + tools/apidoc/gen_toc.py | 1 + ui/scripts/ui-custom/zoneWizard.js | 5 +- wscript_configure | 2 +- 44 files changed, 3300 insertions(+), 3 deletions(-) create mode 100644 plugins/network-elements/bigswitch-vns/pom.xml create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/CreateVnsNetworkAnswer.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/CreateVnsNetworkCommand.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/CreateVnsPortAnswer.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/CreateVnsPortCommand.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/DeleteVnsNetworkAnswer.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/DeleteVnsNetworkCommand.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/DeleteVnsPortAnswer.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/DeleteVnsPortCommand.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/StartupBigSwitchVnsCommand.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/UpdateVnsPortAnswer.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/UpdateVnsPortCommand.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/api/commands/AddBigSwitchVnsDeviceCmd.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/api/commands/DeleteBigSwitchVnsDeviceCmd.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/api/commands/ListBigSwitchVnsDevicesCmd.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/api/commands/VnsConstants.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/api/response/BigSwitchVnsDeviceResponse.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/network/BigSwitchVnsDeviceVO.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/Attachment.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/BigSwitchVnsApi.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/BigSwitchVnsApiException.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/ControlClusterStatus.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/Network.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/Port.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/network/dao/BigSwitchVnsDao.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/network/dao/BigSwitchVnsDaoImpl.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/network/element/BigSwitchVnsElement.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/network/element/BigSwitchVnsElementService.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/network/guru/BigSwitchVnsGuestNetworkGuru.java create mode 100644 plugins/network-elements/bigswitch-vns/src/com/cloud/network/resource/BigSwitchVnsResource.java create mode 100644 plugins/network-elements/bigswitch-vns/test/com/cloud/network/bigswitch/BigSwitchApiTest.java create mode 100644 plugins/network-elements/bigswitch-vns/test/com/cloud/network/resource/BigSwitchVnsResourceTest.java diff --git a/api/src/com/cloud/network/PhysicalNetwork.java b/api/src/com/cloud/network/PhysicalNetwork.java index a495092879e..383b1b67ee0 100644 --- a/api/src/com/cloud/network/PhysicalNetwork.java +++ b/api/src/com/cloud/network/PhysicalNetwork.java @@ -35,7 +35,8 @@ public interface PhysicalNetwork extends Identity, InternalIdentity { VLAN, L3, GRE, - STT; + STT, + VNS; } public enum BroadcastDomainRange { diff --git a/client/pom.xml b/client/pom.xml index 63ec2ef6686..df82402a60e 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -75,6 +75,11 @@ cloud-plugin-network-elb ${project.version} + + org.apache.cloudstack + cloud-plugin-network-vns + ${project.version} + org.apache.cloudstack cloud-plugin-hypervisor-xen diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 4b0506f7543..d70649bf318 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -513,6 +513,12 @@ listNiciraNvpDeviceNetworks=1 # Not implemented (yet) #configureNiciraNvpDevice=1 +#### bigswitch vns commands + +addBigSwitchVnsDevice=1 +deleteBigSwitchVnsDevice=1 +listBigSwitchVnsDevices=1 + #### host simulator commands configureSimulator=1 diff --git a/client/tomcatconf/components.xml.in b/client/tomcatconf/components.xml.in index e84be04638c..c62abe8ff2a 100755 --- a/client/tomcatconf/components.xml.in +++ b/client/tomcatconf/components.xml.in @@ -106,6 +106,7 @@ under the License. + @@ -166,6 +167,7 @@ under the License. + @@ -212,6 +214,7 @@ under the License. + @@ -239,12 +242,14 @@ under the License. + + diff --git a/cloud.spec b/cloud.spec index 9f46dd6fe6c..bde3958d0be 100644 --- a/cloud.spec +++ b/cloud.spec @@ -448,6 +448,7 @@ fi %{_javadir}/%{name}-plugin-hypervisor-xen.jar %{_javadir}/%{name}-plugin-elb.jar %{_javadir}/%{name}-plugin-nicira-nvp.jar +%{_javadir}/%{name}-plugin-bigswitch-vns.jar %config(noreplace) %{_sysconfdir}/%{name}/server/* %doc LICENSE %doc NOTICE diff --git a/debian/cloud-server.install b/debian/cloud-server.install index 9cd1eebb5ff..f792cc2f7cd 100644 --- a/debian/cloud-server.install +++ b/debian/cloud-server.install @@ -24,6 +24,7 @@ /usr/share/java/cloud-plugin-elb.jar /usr/share/java/cloud-plugin-ovs.jar /usr/share/java/cloud-plugin-nicira-nvp.jar +/usr/share/java/cloud-plugin-bigswitch-vns.jar /usr/share/java/cloud-storage-allocator-random.jar /usr/share/java/cloud-user-authenticator-ldap.jar /usr/share/java/cloud-user-authenticator-md5.jar diff --git a/docs/en-US/Release_Notes.xml b/docs/en-US/Release_Notes.xml index c8cc6869737..4d1f62fb713 100644 --- a/docs/en-US/Release_Notes.xml +++ b/docs/en-US/Release_Notes.xml @@ -1291,6 +1291,15 @@ Done restarting router(s). appropriate calls to the Nicira NVP Controller. The plug-in has been tested with Nicira NVP versions 2.1.0, 2.2.0 and 2.2.1. +
+ The BigSwitch Controller Plugin + The BigSwitch Controller plug-in adds OpenFlow based solution for network virtualization + to CloudStack. The plugin supports both BigSwitch commercial controller and the opensource + Floodlight controller. The plugin functions as a provider for CloudStack networks and Connectivity + service. This service is responsible for creating Layer 2 networks supporting the networks + created by guests. When a tenant creates a new network, a virutal network segment will be + created by sending the appropriate calls to the BigSwitch Controller. +
Support for CAStor Cluster CloudStack 4.0.0-incubating supports using a CAStor cluster as the back-end storage diff --git a/plugins/network-elements/bigswitch-vns/pom.xml b/plugins/network-elements/bigswitch-vns/pom.xml new file mode 100644 index 00000000000..32650f31497 --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + cloud-plugin-network-vns + Apache CloudStack Plugin - BigSwitch Virtual Network Segment + + org.apache.cloudstack + cloudstack-plugins + 4.1.0-SNAPSHOT + ../../pom.xml + + diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/CreateVnsNetworkAnswer.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/CreateVnsNetworkAnswer.java new file mode 100644 index 00000000000..e950abe3bed --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/CreateVnsNetworkAnswer.java @@ -0,0 +1,28 @@ +// 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.agent.api; + +public class CreateVnsNetworkAnswer extends Answer { + + public CreateVnsNetworkAnswer(Command command, boolean success, String details) { + super(command, success, details); + } + + public CreateVnsNetworkAnswer(Command command, Exception e) { + super(command, e); + } +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/CreateVnsNetworkCommand.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/CreateVnsNetworkCommand.java new file mode 100644 index 00000000000..df9832889e8 --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/CreateVnsNetworkCommand.java @@ -0,0 +1,52 @@ +// 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.agent.api; + +public class CreateVnsNetworkCommand extends Command { + private String _networkUuid; + private String _name; + private String _tenantUuid; + private int _vlan; + + public CreateVnsNetworkCommand(String networkUuid, String name, String tenantUuid, int vlan) { + this._networkUuid = networkUuid; + this._name = name; + this._tenantUuid = tenantUuid; + this._vlan = vlan; + } + + @Override + public boolean executeInSequence() { + return false; + } + + public String getNetworkUuid() { + return _networkUuid; + } + + public String getName() { + return _name; + } + + public String getTenantUuid() { + return _tenantUuid; + } + + public int getVlan() { + return _vlan; + } +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/CreateVnsPortAnswer.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/CreateVnsPortAnswer.java new file mode 100644 index 00000000000..e88c7b5ffd0 --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/CreateVnsPortAnswer.java @@ -0,0 +1,30 @@ +// 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.agent.api; + +public class CreateVnsPortAnswer extends Answer { + + public CreateVnsPortAnswer(Command command, boolean success, + String details) { + super(command, success, details); + } + + public CreateVnsPortAnswer(Command command, Exception e) { + super(command, e); + } + +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/CreateVnsPortCommand.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/CreateVnsPortCommand.java new file mode 100644 index 00000000000..a4a3a04d702 --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/CreateVnsPortCommand.java @@ -0,0 +1,65 @@ +// 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.agent.api; + +public class CreateVnsPortCommand extends Command { + private String _networkUuid; + private String _portUuid; + private String _tenantUuid; + private String _portName; + private String _mac; + + public CreateVnsPortCommand(String networkUuid, String portUuid, + String tenantUuid, String portName, String mac) { + this._networkUuid = networkUuid; + this._portUuid = portUuid; + this._tenantUuid = tenantUuid; + this._portName = portName; + this._mac = mac; + } + + + public String getNetworkUuid() { + return _networkUuid; + } + + + public String getPortUuid() { + return _portUuid; + } + + + public String getTenantUuid() { + return _tenantUuid; + } + + + public String getPortName() { + return _portName; + } + + + public String getMac() { + return _mac; + } + + @Override + public boolean executeInSequence() { + return false; + } + +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/DeleteVnsNetworkAnswer.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/DeleteVnsNetworkAnswer.java new file mode 100644 index 00000000000..498180c8907 --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/DeleteVnsNetworkAnswer.java @@ -0,0 +1,30 @@ +// 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.agent.api; + +public class DeleteVnsNetworkAnswer extends Answer { + + public DeleteVnsNetworkAnswer(Command command, boolean success, + String details) { + super(command, success, details); + } + + public DeleteVnsNetworkAnswer(Command command, Exception e) { + super(command, e); + } + +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/DeleteVnsNetworkCommand.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/DeleteVnsNetworkCommand.java new file mode 100644 index 00000000000..6cf169bbfc9 --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/DeleteVnsNetworkCommand.java @@ -0,0 +1,41 @@ +// 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.agent.api; + +public class DeleteVnsNetworkCommand extends Command { + + private String _tenantUuid; + private String _networkUuid; + + public DeleteVnsNetworkCommand(String tenantUuid, String networkUuid) { + this._tenantUuid = tenantUuid; + this._networkUuid = networkUuid; + } + + @Override + public boolean executeInSequence() { + return false; + } + + public String get_tenantUuid() { + return _tenantUuid; + } + + public String getNetworkUuid() { + return _networkUuid; + } +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/DeleteVnsPortAnswer.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/DeleteVnsPortAnswer.java new file mode 100644 index 00000000000..00c6abc9971 --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/DeleteVnsPortAnswer.java @@ -0,0 +1,30 @@ +// 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.agent.api; + +public class DeleteVnsPortAnswer extends Answer { + + public DeleteVnsPortAnswer(Command command, boolean success, + String details) { + super(command, success, details); + } + + public DeleteVnsPortAnswer(Command command, Exception e) { + super(command, e); + } + +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/DeleteVnsPortCommand.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/DeleteVnsPortCommand.java new file mode 100644 index 00000000000..0cae01d471d --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/DeleteVnsPortCommand.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.agent.api; + +public class DeleteVnsPortCommand extends Command { + + private String _networkUuid; + private String _portUuid; + private String _tenantUuid; + + public DeleteVnsPortCommand(String networkUuid, String portUuid, String tenantUuid) { + this._networkUuid = networkUuid; + this._portUuid = portUuid; + this._tenantUuid = tenantUuid; + } + + public String getNetworkUuid() { + return _networkUuid; + } + + public String getPortUuid() { + return _portUuid; + } + + public String getTenantUuid() { + return _tenantUuid; + } + + @Override + public boolean executeInSequence() { + return false; + } + +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/StartupBigSwitchVnsCommand.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/StartupBigSwitchVnsCommand.java new file mode 100644 index 00000000000..8310b076370 --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/StartupBigSwitchVnsCommand.java @@ -0,0 +1,27 @@ +// 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.agent.api; + +import com.cloud.host.Host; + +public class StartupBigSwitchVnsCommand extends StartupCommand { + + public StartupBigSwitchVnsCommand() { + super(Host.Type.L2Networking); + } + +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/UpdateVnsPortAnswer.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/UpdateVnsPortAnswer.java new file mode 100644 index 00000000000..6313d144647 --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/UpdateVnsPortAnswer.java @@ -0,0 +1,30 @@ +// 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.agent.api; + +public class UpdateVnsPortAnswer extends Answer { + + public UpdateVnsPortAnswer(Command command, boolean success, + String details) { + super(command, success, details); + } + + public UpdateVnsPortAnswer(Command command, Exception e) { + super(command, e); + } + +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/UpdateVnsPortCommand.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/UpdateVnsPortCommand.java new file mode 100644 index 00000000000..3492b99f3df --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/agent/api/UpdateVnsPortCommand.java @@ -0,0 +1,58 @@ +// 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.agent.api; + +public class UpdateVnsPortCommand extends Command { + private String _networkUuid; + private String _portUuid; + private String _tenantUuid; + private String _portName; + + public UpdateVnsPortCommand(String networkUuid, String portUuid, String tenantUuid, String portName) { + this._networkUuid = networkUuid; + this._portUuid = portUuid; + this._tenantUuid = tenantUuid; + this._portName = portName; + } + + + public String getNetworkUuid() { + return _networkUuid; + } + + + public String getPortUuid() { + return _portUuid; + } + + + public String getTenantUuid() { + return _tenantUuid; + } + + + public String getPortName() { + return _portName; + } + + + @Override + public boolean executeInSequence() { + return false; + } + +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/api/commands/AddBigSwitchVnsDeviceCmd.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/api/commands/AddBigSwitchVnsDeviceCmd.java new file mode 100644 index 00000000000..3662a2ee16d --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/api/commands/AddBigSwitchVnsDeviceCmd.java @@ -0,0 +1,110 @@ +// 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.api.commands; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.PlugService; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.PhysicalNetworkResponse; + +import com.cloud.api.response.BigSwitchVnsDeviceResponse; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.BigSwitchVnsDeviceVO; +import com.cloud.network.element.BigSwitchVnsElementService; +import com.cloud.user.UserContext; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name = "addBigSwitchVnsDevice", responseObject=BigSwitchVnsDeviceResponse.class, description="Adds a BigSwitch VNS device") +public class AddBigSwitchVnsDeviceCmd extends BaseAsyncCmd { + private static final String s_name = "addbigswitchvnsdeviceresponse"; + @PlugService BigSwitchVnsElementService _bigswitchVnsElementService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.UUID, entityType = PhysicalNetworkResponse.class, + required=true, description="the Physical Network ID") + private Long physicalNetworkId; + + @Parameter(name=ApiConstants.HOST_NAME, type=CommandType.STRING, required=true, + description="Hostname of ip address of the BigSwitch VNS Controller.") + private String host; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getPhysicalNetworkId() { + return physicalNetworkId; + } + + public String getHost() { + return host; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { + try { + BigSwitchVnsDeviceVO bigswitchVnsDeviceVO = _bigswitchVnsElementService.addBigSwitchVnsDevice(this); + if (bigswitchVnsDeviceVO != null) { + BigSwitchVnsDeviceResponse response = _bigswitchVnsElementService.createBigSwitchVnsDeviceResponse(bigswitchVnsDeviceVO); + response.setObjectName("bigswitchvnsdevice"); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add BigSwitch VNS device due to internal error."); + } + } catch (InvalidParameterValueException invalidParamExcp) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage()); + } catch (CloudRuntimeException runtimeExcp) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage()); + } + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return UserContext.current().getCaller().getId(); + } + + @Override + public String getEventType() { + return VnsConstants.EVENT_EXTERNAL_VNS_CONTROLLER_ADD; + } + + @Override + public String getEventDescription() { + return "Adding a BigSwitch VNS Controller"; + } +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/api/commands/DeleteBigSwitchVnsDeviceCmd.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/api/commands/DeleteBigSwitchVnsDeviceCmd.java new file mode 100644 index 00000000000..83adb22d091 --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/api/commands/DeleteBigSwitchVnsDeviceCmd.java @@ -0,0 +1,99 @@ +// 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.api.commands; + + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.PlugService; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.SuccessResponse; + +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.element.BigSwitchVnsElementService; +import com.cloud.user.UserContext; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name = "deleteBigSwitchVnsDevice", responseObject=SuccessResponse.class, description=" delete a bigswitch vns device") +public class DeleteBigSwitchVnsDeviceCmd extends BaseAsyncCmd { + private static final String s_name = "deletebigswitchvnsdeviceresponse"; + @PlugService BigSwitchVnsElementService _bigswitchVnsElementService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=VnsConstants.BIGSWITCH_VNS_DEVICE_ID, type=CommandType.LONG, required=true, description="BigSwitch device ID") + private Long bigswitchVnsDeviceId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getBigSwitchVnsDeviceId() { + return bigswitchVnsDeviceId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { + try { + boolean result = _bigswitchVnsElementService.deleteBigSwitchVnsDevice(this); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete BigSwitch device."); + } + } catch (InvalidParameterValueException invalidParamExcp) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage()); + } catch (CloudRuntimeException runtimeExcp) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage()); + } + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return UserContext.current().getCaller().getId(); + } + + @Override + public String getEventType() { + return VnsConstants.EVENT_EXTERNAL_VNS_CONTROLLER_DELETE; + } + + @Override + public String getEventDescription() { + return "Deleting BigSwitch Vns Controller"; + } + +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/api/commands/ListBigSwitchVnsDevicesCmd.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/api/commands/ListBigSwitchVnsDevicesCmd.java new file mode 100644 index 00000000000..d9a209e1f87 --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/api/commands/ListBigSwitchVnsDevicesCmd.java @@ -0,0 +1,109 @@ +// 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.api.commands; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.PlugService; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.PhysicalNetworkResponse; +import org.apache.log4j.Logger; + +import com.cloud.api.response.BigSwitchVnsDeviceResponse; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.BigSwitchVnsDeviceVO; +import com.cloud.network.element.BigSwitchVnsElementService; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name = "listBigSwitchVnsDevices", responseObject=BigSwitchVnsDeviceResponse.class, description="Lists BigSwitch Vns devices") +public class ListBigSwitchVnsDevicesCmd extends BaseListCmd { + public static final Logger s_logger = Logger.getLogger(ListBigSwitchVnsDevicesCmd.class.getName()); + private static final String s_name = "listbigswitchvnsdeviceresponse"; + @PlugService BigSwitchVnsElementService _bigswitchVnsElementService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.UUID, + entityType = PhysicalNetworkResponse.class, + description="the Physical Network ID") + private Long physicalNetworkId; + + @Parameter(name=VnsConstants.BIGSWITCH_VNS_DEVICE_ID, + type=CommandType.LONG, + description="bigswitch vns device ID") + private Long bigswitchVnsDeviceId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getBigSwitchVnsDeviceId() { + return bigswitchVnsDeviceId; + } + + public Long getPhysicalNetworkId() { + return physicalNetworkId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, + ConcurrentOperationException, ResourceAllocationException { + try { + List bigswitchDevices = _bigswitchVnsElementService.listBigSwitchVnsDevices(this); + ListResponse response = new ListResponse(); + List bigswitchDevicesResponse = new ArrayList(); + + if (bigswitchDevices != null && !bigswitchDevices.isEmpty()) { + for (BigSwitchVnsDeviceVO bigswitchDeviceVO : bigswitchDevices) { + BigSwitchVnsDeviceResponse bigswitchDeviceResponse = + _bigswitchVnsElementService.createBigSwitchVnsDeviceResponse(bigswitchDeviceVO); + bigswitchDevicesResponse.add(bigswitchDeviceResponse); + } + } + + response.setResponses(bigswitchDevicesResponse); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } catch (InvalidParameterValueException invalidParamExcp) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage()); + } catch (CloudRuntimeException runtimeExcp) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage()); + } + } + + @Override + public String getCommandName() { + return s_name; + } +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/api/commands/VnsConstants.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/api/commands/VnsConstants.java new file mode 100644 index 00000000000..5a81ec688c6 --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/api/commands/VnsConstants.java @@ -0,0 +1,19 @@ +package com.cloud.api.commands; + + +import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice; + +import com.cloud.network.Network.Provider; + +public class VnsConstants { + public static final String BIGSWITCH_VNS_DEVICE_ID = "vnsdeviceid"; + public static final String BIGSWITCH_VNS_DEVICE_NAME = "bigswitchdevicename"; + + public static final String EVENT_EXTERNAL_VNS_CONTROLLER_ADD = "PHYSICAL.VNSCONTROLLER.ADD"; + public static final String EVENT_EXTERNAL_VNS_CONTROLLER_DELETE = "PHYSICAL.VNSCONTROLLER.DELETE"; + + public static final Provider BigSwitchVns = new Provider("BigSwitchVns", true); + + public static final NetworkDevice BigSwitchVnsDevice = new NetworkDevice("BigSwitchVns", BigSwitchVns.getName()); + +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/api/response/BigSwitchVnsDeviceResponse.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/api/response/BigSwitchVnsDeviceResponse.java new file mode 100644 index 00000000000..ede5adf178e --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/api/response/BigSwitchVnsDeviceResponse.java @@ -0,0 +1,63 @@ +// 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.api.response; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; +import com.cloud.api.commands.VnsConstants; +import com.cloud.network.BigSwitchVnsDeviceVO; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +@EntityReference(value=BigSwitchVnsDeviceVO.class) +public class BigSwitchVnsDeviceResponse extends BaseResponse { + @SerializedName(VnsConstants.BIGSWITCH_VNS_DEVICE_ID) @Param(description="device id of the BigSwitch Vns") + private String id; + + @SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) @Param(description="the physical network to which this BigSwitch Vns belongs to") + private String physicalNetworkId; + + @SerializedName(ApiConstants.PROVIDER) @Param(description="name of the provider") + private String providerName; + + @SerializedName(VnsConstants.BIGSWITCH_VNS_DEVICE_NAME) @Param(description="device name") + private String deviceName; + + @SerializedName(ApiConstants.HOST_NAME) @Param(description="the controller Ip address") + private String hostName; + + public void setId(String vnsDeviceId) { + this.id = vnsDeviceId; + } + + public void setPhysicalNetworkId(String physicalNetworkId) { + this.physicalNetworkId = physicalNetworkId; + } + + public void setProviderName(String providerName) { + this.providerName = providerName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + public void setHostName(String hostName) { + this.hostName = hostName; + } +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/BigSwitchVnsDeviceVO.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/BigSwitchVnsDeviceVO.java new file mode 100644 index 00000000000..7e64833d2b0 --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/BigSwitchVnsDeviceVO.java @@ -0,0 +1,94 @@ +// 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; + +import java.util.UUID; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name="external_bigswitch_vns_devices") +public class BigSwitchVnsDeviceVO { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="uuid") + private String uuid; + + @Column(name="host_id") + private long hostId; + + @Column(name="physical_network_id") + private long physicalNetworkId; + + @Column(name="provider_name") + private String providerName; + + @Column(name="device_name") + private String deviceName; + + public BigSwitchVnsDeviceVO() { + this.uuid = UUID.randomUUID().toString(); + } + + public BigSwitchVnsDeviceVO(long hostId, long physicalNetworkId, + String providerName, String deviceName) { + super(); + this.hostId = hostId; + this.physicalNetworkId = physicalNetworkId; + this.providerName = providerName; + this.deviceName = deviceName; + this.uuid = UUID.randomUUID().toString(); + } + + public long getId() { + return id; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public long getPhysicalNetworkId() { + return physicalNetworkId; + } + + public long getHostId() { + return hostId; + } + + public String getProviderName() { + return providerName; + } + + public String getDeviceName() { + return deviceName; + } + +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/Attachment.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/Attachment.java new file mode 100644 index 00000000000..9a134676d1f --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/Attachment.java @@ -0,0 +1,38 @@ +// 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 Attachment { + private String id; + private String mac; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getMac() { + return mac; + } + + public void setMac(String mac) { + this.mac = mac; + } +} diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/BigSwitchVnsApi.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/BigSwitchVnsApi.java new file mode 100644 index 00000000000..c409dcec9b7 --- /dev/null +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/bigswitch/BigSwitchVnsApi.java @@ -0,0 +1,330 @@ +// 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 java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Type; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.HttpMethodBase; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.cookie.CookiePolicy; +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.methods.StringRequestEntity; +import org.apache.log4j.Logger; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +public class BigSwitchVnsApi { + private static final Logger s_logger = Logger.getLogger(BigSwitchVnsApi.class); + private final static String _protocol = "http"; + private final static String _nsBaseUri = "/networkService/v1.1"; + private final static String _controllerBaseUri = "/wm/core"; + private final static String CONTENT_TYPE = "Content-Type"; + private final static String CONTENT_JSON = "application/json"; + private final static String HTTP_HEADER_INSTANCE_ID = "HTTP_INSTANCE_ID"; + private final static String CLOUDSTACK_INSTANCE_ID = "org.apache.cloudstack"; + private final static MultiThreadedHttpConnectionManager s_httpClientManager = + new MultiThreadedHttpConnectionManager(); + + private String _host; + + private HttpClient _client; + + /* This factory method is protected so we can extend this + * in the unittests. + */ + protected HttpClient createHttpClient() { + return new HttpClient(s_httpClientManager); + } + + protected HttpMethod createMethod(String type, String uri, int port) throws BigSwitchVnsApiException { + String url; + try { + url = new URL(_protocol, _host, port, uri).toString(); + } catch (MalformedURLException e) { + s_logger.error("Unable to build BigSwitch API URL", e); + throw new BigSwitchVnsApiException("Unable to build v API URL", e); + } + + if ("post".equalsIgnoreCase(type)) { + return new PostMethod(url); + } + else if ("get".equalsIgnoreCase(type)) { + return new GetMethod(url); + } + else if ("delete".equalsIgnoreCase(type)) { + return new DeleteMethod(url); + } + else if ("put".equalsIgnoreCase(type)) { + return new PutMethod(url); + } + else { + throw new BigSwitchVnsApiException("Requesting unknown method type"); + } + } + + public BigSwitchVnsApi() { + _client = createHttpClient(); + _client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); + } + + public void setControllerAddress(String address) { + this._host = address; + } + + + /** + * Logs into the BigSwitch API. The cookie is stored in the _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 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 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 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 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'), $('