...
1. Create a directory off of the plugins folder. The name does not matter. Example: cloudstack/plugins/api/timeofday
2. Create a pom.xml in cloudstack/plugins/api/timeofday. Make sure your "parent" relative path points back to plugins/pom.xml, otherwise it won't build. The main entries that matter are the artifactId (cloud-plugin-timeofday), as well as the dependencies.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>cloud-plugin-api-timeofday</artifactId> <name>Apache CloudStack Plugin - TimeOfDay</name> <parent> <groupId>org.apache.cloudstack</groupId> <artifactId>cloudstack-plugins</artifactId> <version>4.1.0-SNAPSHOT</version> <relativePath>../../pom.xml</relativePath> </parent> <dependencies> <dependency> <groupId>org.apache.cloudstack</groupId> <artifactId>cloud-api</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.apache.cloudstack</groupId> <artifactId>cloud-utils</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${cs.mysql.version}</version> <scope>provided</scope> </dependency> </dependencies> <build> <defaultGoal>install</defaultGoal> <sourceDirectory>src</sourceDirectory> <testSourceDirectory>test</testSourceDirectory> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skipTests>true</skipTests> </configuration> <executions> <execution> <phase>integration-test</phase> <goals> <goal>test</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project> |
3. Add a module entry in the modules section of cloudstack/plugins/pom.xml for the new plugin, which will let mvn know that the plugin module needs to be built:
Code Block | ||||
---|---|---|---|---|
| ||||
<module>api/timeofday</module>
|
4. Now create a src, target and test directory off of cloud-plugin-timeofday.
45. Create your code hierarchy ie: com.company.gadget.plugin. For this example I use plugins/api/timeofday/src/com/cloud/test 5
6. Create an interface that extends from PluggableService
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
package com.cloud.test; import com.cloud.utils.component.PluggableService; public interface TimeOfDayManager extends PluggableService { } |
67. Create an implementation of your newly created interface, overriding the getCommands method, and populating it with the classes of each command you want to expose.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
package com.cloud.test; import com.cloud.utils.component.PluggableService; import java.util.List; import java.util.ArrayList; import org.apache.log4j.Logger; import com.cloud.test.GetTimeOfDayCmd; import javax.annotation.PostConstruct; import org.springframework.stereotype.Component; import javax.ejb.Local; @Component @Local(value = { TimeOfDayManager.class }) public class TimeOfDayManagerImpl implements TimeOfDayManager { private static final Logger s_logger = Logger.getLogger(TimeOfDayManagerImpl.class); public TimeOfDayManagerImpl() { super(); } @Override public List<Class<?>> getCommands() { List<Class<?>> cmdList = new ArrayList<Class<?>>(); cmdList.add(GetTimeOfDayCmd.class); return cmdList; } } |
78. Write a command class that implements the correct annotations for a command:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
package com.cloud.test; import javax.inject.Inject; import org.apache.log4j.Logger; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.Parameter; @APICommand(name = "getTimeOfDay", description="Get Cloudstack's time of day", responseObject = GetTimeOfDayCmdResponse.class, includeInApiDoc=true) public class GetTimeOfDayCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(GetTimeOfDayCmd.class.getName()); private static final String s_name = "gettimeofdayresponse"; @Parameter(name="example", type=CommandType.STRING, required=false, description="Just an example string that will be uppercased") private String example; public String getExample() { return this.example; } @Override public void execute() { GetTimeOfDayCmdResponse response = new GetTimeOfDayCmdResponse(); if ( this.example != null ) { response.setExampleEcho(example); } response.setObjectName("timeofday"); // the inner part of the json structure response.setResponseName(getCommandName()); // the outer part of the json structure this.setResponseObject(response); } @Override public String getCommandName() { return s_name; } @Override public long getEntityOwnerId() { return 0; } } |
89. Write a Response class for the command:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
package com.cloud.test; import org.apache.cloudstack.api.ApiConstants; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; import org.apache.cloudstack.api.BaseResponse; import java.util.Date; import java.text.SimpleDateFormat; @SuppressWarnings("unused") public class GetTimeOfDayCmdResponse extends BaseResponse { @SerializedName(ApiConstants.IS_ASYNC) @Param(description="true if api is asynchronous") private Boolean isAsync; @SerializedName("timeOfDay") @Param(description="The time of day from CloudStack") private String timeOfDay; @SerializedName("exampleEcho") @Param(description="An upper cased string") private String exampleEcho; public GetTimeOfDayCmdResponse(){ this.isAsync = false; SimpleDateFormat dateformatYYYYMMDD = new SimpleDateFormat("yyyyMMdd hh:mm:ss"); this.setTimeOfDay( (new StringBuilder( dateformatYYYYMMDD.format( new Date() ) )).toString() ); } public void setAsync(Boolean isAsync) { this.isAsync = isAsync; } public boolean getAsync() { return isAsync; } public void setTimeOfDay(String timeOfDay) { this.timeOfDay = timeOfDay; } public void setExampleEcho(String exampleEcho) { this.exampleEcho = exampleEcho.toUpperCase(); } } |
910. Update client/tomcatconf/componentContext.xml.in and add your new manager to it's its configuration:
Code Block | ||||
---|---|---|---|---|
| ||||
<bean id="timeOfDayManagerImpl" class="com.cloud.test.TimeOfDayManagerImpl"> </bean> |
1011. Lastly, update client/tomcatconf/commands.properties.in, and add the command name (for the example this would be getTimeOfDay as stated in the @APICommand annotation).
1112. You can test your new command via the browser, cloudmonkey or even curl. Here is a simple perl script that shows how to test the new getTimeOfDay command.
...