Skip to content
OpenStack Java SDK
Java
Branch: master
Clone or download

Latest commit

Fetching latest commit…
Cannot retrieve the latest commit at this time.

Files

Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
META-INF
etc
src
.classpath
.gitignore
.project
LICENSE
README.md
pom.xml

README.md

What's openstack ?

OpenStack是一个IaaS层基础资源管理平台,由Nova、Cinder、Neutron等主要的组件组合起来,提供计算服务、存储服务、网络服务等云服务,为公共及私有云的建设与管理提供一种开源实现方案。它最初是由 Rackspace 和 NASA 共同开发帮助服务商和企业内部实现类似于 Amazon EC2 和 S3 的云基础架构服务(Infrastructure as a Service, IaaS),更多信息科参考openstack官网

关于此项目

Openstack提供了Python接口以及RESTFul API,但却一直没有Java版本的SDK,这个项目的最终目的就是要实现一个便于调用、易于扩展的Openstack Java SDK包,为Java开发人员提供直接访问和管理Openstack平台的接口,弥补Openstack API的不足。它是基于Openstack RESTFul的二次开发。最初应实验室需求而开展工作,目前已经花了陆陆续续近1个月的时间,实现了基本功能。当然存在很多bug以及许多尚未实现的功能。

如何使用

本项目使用Maven构建,因此首先使用mvn命令构建本项目:

mvn package

如果需要把依赖包一块打进一个包,可以使用以下命令实现:

mvn assembly:assembly

项目运行时需要配置文件,配置文件路径由系统变量OPENSTACK_CONF_PATH指定,默认为/etc/openstack,参考配置文件说明 该项目设计模式参考了Openstack官方Python库的设计理念,尽力做到调用简单、利于扩展并可实现热插拔.以下是一个简单的使用例子:

	OpenstackSession session = OpenstackSession.getSession("username", "password");// get session
	Nova nova = session.getNovaClient(); // get nova client
	// get a flavor list, print their name
	for (Flavor flavor : nova.flavors.list()) {
		System.out.println(flavor.getName());
	}
	// create a new server
	Server server = new Server();
	server.setName("demo");
	server.setImageRef("imageId");
	server.setFlavorRef("flavorId");
	// some other config 
	nova.servers.create(server); // call create method to execute.

加入开发

由于时间有限,此时此刻正忙于写毕设论文,短期内要完成所有功能实在有难度。因此希望有更多的大牛加入,共同推进完善。也欢迎指出目前代码的不足之处,甚至重构整个代码。

下面介绍如何扩展新接口的步骤:

Step 1:创建model

model就是实体对应的Java Bean,接收请求过来的数据一般是Json,要把Json表示的对象转化成的Java对象。你完全可以自定义Bean,或者继承AbstractEntity,属性使用Property注解,构造方法需要传递一个JSONObject对象,一般直接调用基类的构造方法就能完成JSONObject到Java Bean的转化。以下是Model实例:

@Entity("volume_type")
public class VolumeType extends AbstractEntity {
	private static final long serialVersionUID = -6539238104579991330L;
	@Property("extra_specs")
	private JSONObject metadata;
	/*
	@Property("name")
	private String name;
	@Property("id")
	private String id;
	*/
	public VolumeType() {
		super();
	}
	public VolumeType(JSONObject jsonObj) {
		super(jsonObj);
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	// some other getter and setter here
}

Step 2:创建Bean Manager接口

Manager接口即对Bean定义可实现的操作,这些操作可能因API的版本不同有不同的实现。在设计接口时,没有使用共同接口,也尚未使用接口继承,原因是很多实体Bean对应的操作差异性很大,即使是相同的操作,参数也不完全相同。下面是一个Manager接口实例:

public interface ServerManager {
	/**
	 * Get a server.
	 * @param id ID of the Server to get.
	 * @return Server
	 * @throws OperationException
	 */
	Server get(String id) throws OperationException;
	/**
	 * Get a list of servers.
	 * @return List of server
	 * @throws OperationException
	 */
	List<Server> list() throws OperationException;
	/**
	 * Stop(power off) the server
	 * @param id The id of server to stop.
	 * @throws OperationException
	 */
	void stop(String id) throws OperationException;
	/**
	 * Start(power on) the server,
	 * @param id The id of server to start.
	 * @throws OperationException
	 */
	 void start(String id) throws OperationException;
	 /**
	  * Reboot a server, for a software-lever reboot
	  * @param id The ID of server to reboot.
	  * @see reboot(String id, boolean hard)
	  */
	 void reboot(String id) throws OperationException;
	 /**
	  * update the name for a Server
	  * @param id the id of server to rename
	  * @param name the new name of the server.
	  * @throws OperationException
	  */
	 void rename(String id, String name) throws OperationException;
	 /**
	  * Create (boot) a new Server.<br/>
	  * <i>Remember</i> : You must set name, imageRef, flavorRef !
	  * @param instance The new server you have created.
	  * @return
	  * @throws OperationException
	  */
	 Server create(Server instance) throws OperationException;
	 /**
	  * Delete (i.e shut down and delete the image) this server.
	  * @param id The ID of server to delete.
	  * @throws OperationException
	  */
	 void delete(String id) throws OperationException;
}

Step 3: 实现Manager接口

接下来就是接口的具体实现,可能会因API版本不同而有不同的实现,实际应用时可以根据配置文件指定需要使用的版本。

public class Flavors extends AbstractManager<Flavor> implements FlavorManager{
	private final String PREFIX = "/flavors";
	public Flavors(Authenticated credentical) {
		super(credentical, Flavor.class);
	}
	/**
	 * Get a list of all flavors
	 * @return A List , which holds flavors
	 * @throws OperationException
	 */
	@Override
	public List<Flavor> list() throws OperationException {
		return _list(PREFIX + "/detail");
	}
	/**
	 * Get a specific Flavor.
	 * @param id The ID of Flavor to get. 
	 * @return Flavor
	 * @throws OperationException
	 */
	@Override
	public Flavor get(String id) throws OperationException {
		return _get(PREFIX + "/" + id);
	}
	/**
	 * Delete a specific Flavor.
	 * @param id The ID of Flavor to delete.
	 * @throws OperationException
	 */
	@Override
	public void delete(String id) throws OperationException {
		_delete("/flavors/" + id);
	}
	/**
	 * create a new flavor for a tenant
	 * @param flavor The flavor to create
	 * @return The new flavor
	 * @throws OperationException
	 */
	@Override
	public Flavor create(Flavor flavor) throws OperationException {
		return _create("/flavors", flavor);
	}
}

Step 4: 注册新接口

注册新功能就是把相应的Manager接口添加到Client下(比如Nova, Glance等),目前我直接硬编码,实际操作应该根据配置文件选择api版本由工厂负责创建,以下是实例:

public class Nova {
	public final FlavorManager flavors;
	public final HypervisorManager hypervisors;
	public final ServerManager servers;
	public final KeyPairManager keypairs;
	public Nova(Authenticated credentical) {
		// bad work, don't do that!!
		flavors = new Flavors(credentical);
		hypervisors = new Hypervisors(credentical);
		servers = new Servers(credentical);
		keypairs = new KeyPairs(credentical);
	}

如何扩展新功能

如何为已经实现的接口增加新功能,比如在请求前记录日志,或者使用Cache。只需要增加装饰器即可!以下是一个简单的实例:

public class FlavorCachedManager implements FlavorManager {
	private FlavorManager flavors;
	public FlavorCachedManager(FlavorManager flavors) {
		this.flavors = flavors;
	}
	@Override
	public Flavor get(String id) throws OperationException {
		Flavor flavor = getFromCache(id);
		if (flavor == null) {
			flavor = flavors.get(id);
		}
		addToCache(flavor);
		return flavor;
	}

}

Copyright

The MIT License (MIT)

You can’t perform that action at this time.