diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index c539066bdaa..d3c29e93028 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -398,6 +398,8 @@ public class EventTypes { public static final String EVENT_EXTERNAL_NVP_CONTROLLER_ADD = "PHYSICAL.NVPCONTROLLER.ADD"; public static final String EVENT_EXTERNAL_NVP_CONTROLLER_DELETE = "PHYSICAL.NVPCONTROLLER.DELETE"; public static final String EVENT_EXTERNAL_NVP_CONTROLLER_CONFIGURE = "PHYSICAL.NVPCONTROLLER.CONFIGURE"; + public static final String EVENT_EXTERNAL_OVS_CONTROLLER_ADD = "PHYSICAL.OVSCONTROLLER.ADD"; + public static final String EVENT_EXTERNAL_OVS_CONTROLLER_DELETE = "PHYSICAL.OVSCONTROLLER.DELETE"; // AutoScale public static final String EVENT_COUNTER_CREATE = "COUNTER.CREATE"; diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index efdff12b0c6..0cde5bad113 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -409,6 +409,10 @@ public class ApiConstants { public static final String VSWITCH_TYPE_PUBLIC_TRAFFIC = "publicvswitchtype"; public static final String VSWITCH_NAME_GUEST_TRAFFIC = "guestvswitchname"; public static final String VSWITCH_NAME_PUBLIC_TRAFFIC = "publicvswitchname"; + // Ovs controller + public static final String OVS_DEVICE_ID = "ovsdeviceid"; + public static final String OVS_DEVICE_NAME = "ovsdevicename"; + public static final String EXTERNAL_SWITCH_MGMT_DEVICE_ID = "vsmdeviceid"; public static final String EXTERNAL_SWITCH_MGMT_DEVICE_NAME = "vsmdevicename"; public static final String EXTERNAL_SWITCH_MGMT_DEVICE_STATE = "vsmdevicestate"; diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in new file mode 100644 index 00000000000..1f3571c990b --- /dev/null +++ b/client/tomcatconf/applicationContext.xml.in @@ -0,0 +1,941 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.apache.cloudstack.framework + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 10afdcc7e63..da4c03fc71c 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -591,6 +591,12 @@ addBigSwitchVnsDevice=1 deleteBigSwitchVnsDevice=1 listBigSwitchVnsDevices=1 +#### ovs commands + +addOvsDevice=1 +deleteOvsDevice=1 +listOvsDevices=1 + #### host simulator commands configureSimulator=1 diff --git a/plugins/network-elements/ovs/resources/META-INF/cloudstack/ovs/spring-ovs-context.xml b/plugins/network-elements/ovs/resources/META-INF/cloudstack/ovs/spring-ovs-context.xml index 9180eebd040..e60d93e08a1 100644 --- a/plugins/network-elements/ovs/resources/META-INF/cloudstack/ovs/spring-ovs-context.xml +++ b/plugins/network-elements/ovs/resources/META-INF/cloudstack/ovs/spring-ovs-context.xml @@ -36,5 +36,7 @@ + + diff --git a/plugins/network-elements/ovs/src/com/cloud/api/response/OvsDeviceResponse.java b/plugins/network-elements/ovs/src/com/cloud/api/response/OvsDeviceResponse.java new file mode 100644 index 00000000000..c0901b224e1 --- /dev/null +++ b/plugins/network-elements/ovs/src/com/cloud/api/response/OvsDeviceResponse.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.api.response; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import com.cloud.network.ovs.dao.OvsDeviceVO; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +@EntityReference(value = OvsDeviceVO.class) +public class OvsDeviceResponse extends BaseResponse { + + @SerializedName(ApiConstants.OVS_DEVICE_ID) + @Param(description = "device id of the Ovs") + private String id; + + @SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) + @Param(description = "the physical network to which this device belongs to") + private String physicalNetworkId; + + @SerializedName(ApiConstants.OVS_DEVICE_NAME) + @Param(description = "device name") + private String deviceName; + + @SerializedName(ApiConstants.HOST_NAME) + @Param(description = "the controller Ip address") + private String hostName; + + public String getId() { + return this.id; + } + + public void setId(String vnsDeviceId) { + this.id = vnsDeviceId; + } + + public void setPhysicalNetworkId(String physicalNetworkId) { + this.physicalNetworkId = physicalNetworkId; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + public void setHostName(String hostName) { + this.hostName = hostName; + } +} diff --git a/plugins/network-elements/ovs/src/com/cloud/network/commands/AddOvsDeviceCmd.java b/plugins/network-elements/ovs/src/com/cloud/network/commands/AddOvsDeviceCmd.java new file mode 100644 index 00000000000..1abc32475d5 --- /dev/null +++ b/plugins/network-elements/ovs/src/com/cloud/network/commands/AddOvsDeviceCmd.java @@ -0,0 +1,116 @@ +// 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.commands; + +import javax.inject.Inject; + +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.ServerApiException; +import org.apache.cloudstack.api.response.PhysicalNetworkResponse; + +import com.cloud.api.response.OvsDeviceResponse; +import com.cloud.event.EventTypes; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.element.OvsElementService; +import com.cloud.network.ovs.dao.OvsDeviceVO; +import com.cloud.user.UserContext; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name = "addDevice", responseObject = OvsDeviceResponse.class, description = "Adds a Ovs controller device") +public class AddOvsDeviceCmd extends BaseAsyncCmd { + private static final String s_name = "adddeviceresponse"; + @Inject + OvsElementService _ovsElementService; + + // /////////////////////////////////////////////////// + // ////////////// 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, + NetworkRuleConflictException { + try { + OvsDeviceVO ovsDeviceVO = _ovsElementService.addOvsDevice(this); + if (ovsDeviceVO != null) { + OvsDeviceResponse response = _ovsElementService + .createOvsDeviceResponse(ovsDeviceVO); + response.setObjectName("ovsdevice"); + 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 getEventType() { + return EventTypes.EVENT_EXTERNAL_OVS_CONTROLLER_ADD; + } + + @Override + public String getEventDescription() { + return "Adding an Ovs Controller"; + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return UserContext.current().getCaller().getId(); + } + +} diff --git a/plugins/network-elements/ovs/src/com/cloud/network/commands/DeleteOvsDeviceCmd.java b/plugins/network-elements/ovs/src/com/cloud/network/commands/DeleteOvsDeviceCmd.java new file mode 100644 index 00000000000..87eedfb6a1a --- /dev/null +++ b/plugins/network-elements/ovs/src/com/cloud/network/commands/DeleteOvsDeviceCmd.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.network.commands; + +import javax.inject.Inject; + +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.ServerApiException; +import org.apache.cloudstack.api.response.SuccessResponse; + +import com.cloud.api.response.OvsDeviceResponse; +import com.cloud.event.EventTypes; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.element.OvsElementService; +import com.cloud.user.UserContext; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name = "deleteOvsDevice", responseObject = SuccessResponse.class, description = " delete a ovs device") +public class DeleteOvsDeviceCmd extends BaseAsyncCmd { + private static final String s_name = "deleteovsdeviceresponse"; + @Inject + OvsElementService _ovsElementService; + + // /////////////////////////////////////////////////// + // ////////////// API parameters ///////////////////// + // /////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.OVS_DEVICE_ID, type = CommandType.UUID, entityType = OvsDeviceResponse.class, required = true, description = "Ovs device ID") + private Long ovsDeviceId; + + // /////////////////////////////////////////////////// + // ///////////////// Accessors /////////////////////// + // /////////////////////////////////////////////////// + + public Long getOvsDeviceId() { + return ovsDeviceId; + } + + // /////////////////////////////////////////////////// + // ///////////// API Implementation/////////////////// + // /////////////////////////////////////////////////// + @Override + public void execute() throws ResourceUnavailableException, + InsufficientCapacityException, ServerApiException, + ConcurrentOperationException, ResourceAllocationException, + NetworkRuleConflictException { + try { + boolean result = _ovsElementService.deleteOvsDevice(this); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, + "Failed to delete Ovs 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 getEventType() { + return EventTypes.EVENT_EXTERNAL_OVS_CONTROLLER_DELETE; + } + + @Override + public String getEventDescription() { + return "Deleting Ovs Controller"; + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return UserContext.current().getCaller().getId(); + } + +} diff --git a/plugins/network-elements/ovs/src/com/cloud/network/commands/ListOvsDevicesCmd.java b/plugins/network-elements/ovs/src/com/cloud/network/commands/ListOvsDevicesCmd.java new file mode 100644 index 00000000000..2adb33af482 --- /dev/null +++ b/plugins/network-elements/ovs/src/com/cloud/network/commands/ListOvsDevicesCmd.java @@ -0,0 +1,114 @@ +// 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.commands; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +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.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.OvsDeviceResponse; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.element.OvsElementService; +import com.cloud.network.ovs.dao.OvsDeviceVO; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name = "listOvsDevices", responseObject = OvsDeviceResponse.class, description = "Lists Ovs devices") +public class ListOvsDevicesCmd extends BaseListCmd { + public static final Logger s_logger = Logger + .getLogger(ListOvsDevicesCmd.class.getName()); + private static final String s_name = "listovsdeviceresponse"; + @Inject + OvsElementService _ovsElementService; + + // /////////////////////////////////////////////////// + // ////////////// API parameters ///////////////////// + // /////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.PHYSICAL_NETWORK_ID, type = CommandType.UUID, entityType = PhysicalNetworkResponse.class, description = "the Physical Network ID") + private Long physicalNetworkId; + + @Parameter(name = ApiConstants.OVS_DEVICE_ID, type = CommandType.UUID, entityType = OvsDeviceResponse.class, description = "ovs device ID") + private Long ovsDeviceId; + + // /////////////////////////////////////////////////// + // ///////////////// Accessors /////////////////////// + // /////////////////////////////////////////////////// + + public Long getOvsDeviceId() { + return ovsDeviceId; + } + + public Long getPhysicalNetworkId() { + return physicalNetworkId; + } + + // /////////////////////////////////////////////////// + // ///////////// API Implementation/////////////////// + // /////////////////////////////////////////////////// + @Override + public void execute() throws ResourceUnavailableException, + InsufficientCapacityException, ServerApiException, + ConcurrentOperationException, ResourceAllocationException, + NetworkRuleConflictException { + try { + List ovsDevices = _ovsElementService + .listOvsDevices(this); + ListResponse response = new ListResponse(); + List ovsDevicesResponse = new ArrayList(); + + if (ovsDevices != null && !ovsDevices.isEmpty()) { + for (OvsDeviceVO ovsDeviceVO : ovsDevices) { + OvsDeviceResponse ovsDeviceResponse = _ovsElementService + .createOvsDeviceResponse(ovsDeviceVO); + ovsDevicesResponse.add(ovsDeviceResponse); + } + } + + response.setResponses(ovsDevicesResponse); + 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/ovs/src/com/cloud/network/element/OvsElement.java b/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java index 18b7a90829f..0ec54e35657 100644 --- a/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java +++ b/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java @@ -16,12 +16,14 @@ // under the License. package com.cloud.network.element; +import java.util.List; import java.util.Map; import java.util.Set; import javax.ejb.Local; import javax.inject.Inject; +import com.cloud.api.response.OvsDeviceResponse; import com.cloud.deploy.DeployDestination; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; @@ -32,9 +34,14 @@ import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.Networks; import com.cloud.network.PhysicalNetworkServiceProvider; +import com.cloud.network.commands.AddOvsDeviceCmd; +import com.cloud.network.commands.DeleteOvsDeviceCmd; +import com.cloud.network.commands.ListOvsDevicesCmd; import com.cloud.network.ovs.OvsTunnelManager; +import com.cloud.network.ovs.dao.OvsDeviceVO; import com.cloud.offering.NetworkOffering; import com.cloud.utils.component.AdapterBase; +import com.cloud.utils.db.DB; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; import com.cloud.vm.VirtualMachineProfile; diff --git a/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElementService.java b/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElementService.java new file mode 100644 index 00000000000..b55fe6b6c92 --- /dev/null +++ b/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElementService.java @@ -0,0 +1,22 @@ +package com.cloud.network.element; + +import java.util.List; + +import com.cloud.api.response.OvsDeviceResponse; +import com.cloud.network.commands.AddOvsDeviceCmd; +import com.cloud.network.commands.DeleteOvsDeviceCmd; +import com.cloud.network.commands.ListOvsDevicesCmd; +import com.cloud.network.ovs.dao.OvsDeviceVO; +import com.cloud.utils.component.PluggableService; + +public interface OvsElementService extends PluggableService { + + public OvsDeviceVO addOvsDevice(AddOvsDeviceCmd cmd); + + public OvsDeviceResponse createOvsDeviceResponse(OvsDeviceVO ovsDeviceVO); + + public boolean deleteOvsDevice(DeleteOvsDeviceCmd cmd); + + public List listOvsDevices(ListOvsDevicesCmd cmd); + +} diff --git a/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsApi.java b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsApi.java new file mode 100644 index 00000000000..b5333122edc --- /dev/null +++ b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsApi.java @@ -0,0 +1,78 @@ +// 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.ovs; + +import java.net.MalformedURLException; +import java.net.URL; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; +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.log4j.Logger; + +public class OvsApi { + private static final Logger s_logger = Logger.getLogger(OvsApi.class); + private final static String _protocol = "http"; + private final static MultiThreadedHttpConnectionManager s_httpClientManager = new MultiThreadedHttpConnectionManager(); + + private String _host; + + private final HttpClient _client; + + protected HttpClient createHttpClient() { + return new HttpClient(s_httpClientManager); + } + + protected HttpMethod createMethod(String type, String uri, int port) + throws OvsApiException { + String url; + try { + url = new URL(_protocol, _host, port, uri).toString(); + } catch (MalformedURLException e) { + s_logger.error("Unable to build Ovs API URL", e); + throw new OvsApiException("Unable to Ovs 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 OvsApiException("Requesting unknown method type"); + } + } + + public OvsApi() { + _client = createHttpClient(); + _client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); + } + + public void setControllerAddress(String address) { + this._host = address; + } + + // TODO: implement requests +} diff --git a/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsApiException.java b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsApiException.java new file mode 100644 index 00000000000..20603e01eff --- /dev/null +++ b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsApiException.java @@ -0,0 +1,35 @@ +// 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.ovs; + +public class OvsApiException extends Exception { + + public OvsApiException() { + } + + public OvsApiException(String message) { + super(message); + } + + public OvsApiException(Throwable cause) { + super(cause); + } + + public OvsApiException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/plugins/network-elements/ovs/src/com/cloud/network/ovs/StartupOvsCommand.java b/plugins/network-elements/ovs/src/com/cloud/network/ovs/StartupOvsCommand.java new file mode 100644 index 00000000000..b85331ef70e --- /dev/null +++ b/plugins/network-elements/ovs/src/com/cloud/network/ovs/StartupOvsCommand.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.network.ovs; + +import com.cloud.agent.api.StartupCommand; +import com.cloud.host.Host; + +public class StartupOvsCommand extends StartupCommand { + + public StartupOvsCommand() { + super(Host.Type.L2Networking); + } +} diff --git a/plugins/network-elements/ovs/src/com/cloud/network/resource/OvsResource.java b/plugins/network-elements/ovs/src/com/cloud/network/resource/OvsResource.java new file mode 100644 index 00000000000..a94e4f8d456 --- /dev/null +++ b/plugins/network-elements/ovs/src/com/cloud/network/resource/OvsResource.java @@ -0,0 +1,175 @@ +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.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.host.Host; +import com.cloud.host.Host.Type; +import com.cloud.network.ovs.OvsApi; +import com.cloud.network.ovs.StartupOvsCommand; +import com.cloud.resource.ServerResource; +import com.cloud.utils.component.ManagerBase; + +public class OvsResource extends ManagerBase implements ServerResource { + private static final Logger s_logger = Logger.getLogger(OvsResource.class); + + private String _name; + private String _guid; + private String _zoneId; + private int _numRetries; + + private OvsApi _ovsApi; + + protected OvsApi createOvsApi() { + return new OvsApi(); + } + + @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"); + } + + _ovsApi = createOvsApi(); + _ovsApi.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() { + return Host.Type.L2Networking; + } + + @Override + public StartupCommand[] initialize() { + StartupOvsCommand sc = new StartupOvsCommand(); + 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) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Answer executeRequest(Command cmd) { + return executeRequest(cmd, _numRetries); + } + + private Answer executeRequest(ReadyCommand cmd) { + return new ReadyAnswer(cmd); + } + + private Answer executeRequest(MaintainCommand cmd) { + return new MaintainAnswer(cmd); + } + + public Answer executeRequest(Command cmd, int numRetries) { + if (cmd instanceof ReadyCommand) { + return executeRequest((ReadyCommand) cmd); + } else if (cmd instanceof MaintainCommand) { + return executeRequest((MaintainCommand) cmd); + } + // TODO: implement services request + // else if (cmd instanceof CreateOvsNetworkCommand) { + // return executeRequest((CreateOvsNetworkCommand)cmd, numRetries); + // } + // else if (cmd instanceof DeleteOvsNetworkCommand) { + // return executeRequest((DeleteOvsNetworkCommand) cmd, numRetries); + // } + // else if (cmd instanceof CreateOvsPortCommand) { + // return executeRequest((CreateOvsPortCommand) cmd, numRetries); + // } + // else if (cmd instanceof DeleteOvsPortCommand) { + // return executeRequest((DeleteOvsPortCommand) cmd, numRetries); + // } + // else if (cmd instanceof UpdateOvsPortCommand) { + // return executeRequest((UpdateOvsPortCommand) cmd, numRetries); + // } + s_logger.debug("Received unsupported command " + cmd.toString()); + return Answer.createUnsupportedCommandAnswer(cmd); + } + + @Override + public void disconnected() { + } + + 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); + } + } + + @Override + public IAgentControl getAgentControl() { + return null; + } + + @Override + public void setAgentControl(IAgentControl agentControl) { + } + +} diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 55cb4cce7b9..bf32b8d7869 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -196,6 +196,8 @@ DROP TABLE IF EXISTS `cloud`.`vm_network_map`; DROP TABLE IF EXISTS `cloud`.`netapp_volume`; DROP TABLE IF EXISTS `cloud`.`netapp_pool`; DROP TABLE IF EXISTS `cloud`.`netapp_lun`; +DROP TABLE IF EXISTS `cloud`.`ovs_devices`; +DROP TABLE IF EXISTS `cloud`.`ovs_nic_map`; CREATE TABLE `cloud`.`version` ( `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT COMMENT 'id', @@ -2475,5 +2477,25 @@ CREATE TABLE `cloud`.`nicira_nvp_nic_map` ( CONSTRAINT `fk_nicira_nvp_nic_map__nic` FOREIGN KEY(`nic`) REFERENCES `nics`(`uuid`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `cloud`.`ovs_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 ovs device is added', + `device_name` varchar(255) NOT NULL COMMENT 'name of the ovs device', + `host_id` bigint unsigned NOT NULL COMMENT 'host id coresponding to the ovs device', + PRIMARY KEY (`id`), + CONSTRAINT `fk_ovs_devices__host_id` FOREIGN KEY (`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_ovs_devices__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`ovs_nic_map` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `logicalswitch` varchar(255) NOT NULL COMMENT 'uuid of logical switch this port is provisioned on', + `logicalswitchport` varchar(255) UNIQUE COMMENT 'uuid of this logical switch port', + `nic` varchar(255) UNIQUE COMMENT 'cloudstack uuid of the nic connected to this logical switch port', + PRIMARY KEY (`id`), + CONSTRAINT `fk_ovs_nic_map__nic` FOREIGN KEY(`nic`) REFERENCES `nics`(`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + SET foreign_key_checks = 1;