...
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>
|
...
6. Create an interface that extends from PluggableService
Code Block | lang | java|||||
---|---|---|---|---|---|---|
| ||||||
package com.cloud.test;
import com.cloud.utils.component.PluggableService;
public interface TimeOfDayManager extends PluggableService { }
|
7. 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 | lang | java|||||
---|---|---|---|---|---|---|
| ||||||
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;
}
}
|
8. Write a command class that implements the correct annotations for a command:
Code Block | lang | java|||||
---|---|---|---|---|---|---|
| ||||||
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;
}
}
|
9. 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();
}
}
|
10. Update client/tomcatconf/componentContext.xml.in and add your new manager to its configuration:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<bean id="timeOfDayManagerImpl" class="com.cloud.test.TimeOfDayManagerImpl"> </bean>
|
The above is now obsolete. Instead in your plugin folder you need to add this context, for example in this case:
11. Update client/tomcatconf/commands.properties.in, and add the command name (for the example this would be getTimeOfDay as stated in the @APICommand annotation).
...
13. 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.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
#!/usr/bin/env perl
use strict;
use Data::Dumper;
use LWP::Simple;
use Mojo::JSON 'j';
my $content = j(get("http://localhost:8096/client/api?command=getTimeOfDay&response=json&example=moo"));
print Dumper($content);
|
And here is the output
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
$VAR1 = {
'gettimeofdayresponse' => {
'timeofday' => {
'timeOfDay' => '20130404 09:24:00',
'exampleEcho' => 'MOO',
'isasync' => bless( do{\(my $o = 0)}, 'Mojo::JSON::_Bool' )
}
}
};
|