Cloud driver是一個開放的接口,用戶可實現該接口開發本身的cloud diver,以支持特定的私有云,或者對公共雲環境建立更多細粒度的配置。在建立本身的cloud driver 時,須要考慮或調整已有cloud driver配置中的一些項,以下。 java
加載自定義類文件——cloud driver 的實現類必須相對啓動雲的客戶端和Cloudify ESM 管理組件是可用的。當前,對於cloud driver開發者的工做是,保證組件須要的類在相應的類路徑中。例如,添加包含相應類的jar包到Cloudify distribution( <cloudifyRoot>/lib/required),這些jar文件會自動地添加到全部組件的類路徑下。而且添加到distribution以後,在啓動新的machines時,這些類都是可用的。典型地,distribution從本地網絡文件存儲中下載(e.g. Amazon S3 in the case of Amazon)。 node
加載自定義啓動腳本——一旦bootstrap或橫向展成功的啓動一個新的machine,啓動腳本就會經過SSH在遠程machine上執行。這個腳本負責下載和安裝Cloudify,並啓動Cloudify agent。在一些實施中,可能須要調整這個過程來適應特定環境的需求(好比系統代理 、掛載點、和paths)。可使用默認的啓動腳本(bootstrap-management.sh),適用於內置的cloud driver,也可做爲自定義cloud driver的基本啓動腳本。簡單的將修改後的腳本放置到upload文件夾,它將會自動上傳到每個新的machine中。 git
爲了解釋cloud driver的情景,咱們使用Openstack cloud driver(OpenstackCloudDriver)繼承CloudDriverSupport基類,而且實現ProvisioningDriver接口。 github
1)Cloudify cloud driver(接口名:ProvisioningDriver)是一個Java POJO,使用一個配置文件來定義cloud特定的屬性,和在如下主要場景有相對應的方法。 web
2)啓動雲——分配machines,安裝Cloudify controller。 shell
安裝應用——爲應用服務分配machines,安裝應用程序的服務(包括Cloudify agent)。在這種場景下,在management machine上的cloud driver做爲Cloudify controller的一部分。 json
注: Cluster healing的場景會被Cloudify看成與安裝應用的場景同樣。 bootstrap
3)卸載應用——關閉應用服務,並經過服務命令cloud driver關閉相應的machines。 api
4)關閉雲——卸載全部Cloudify的machine和組件。 數組
這種狀況下,cloud driver在client machine上,並不在 Cloudify controller的management machines上存在。在Cloudify shell提示符,用戶運行bootstrap命令以指定cloud driver的實現。Cloud driver被shell實例化,同時she經過調用setConfig方法傳遞Driver中的引用配置對象(org.cloudifysource.dsl.cloud.Cloud)
@Override public void setConfig(final Cloud cloud, final String templateName, final boolean management) { super.setConfig( cloud, templateName, management); if (this.management) { this.serverNamePrefix = this.cloud.getProvider().getManagementGroup(); } else { this.serverNamePrefix = this.cloud.getProvider().getMachineNamePrefix(); } this.tenant = (String) this.cloud.getCustom().get( OPENSTACK_TENANT); if (tenant == null) { throw new IllegalArgumentException("Custom field '" + OPENSTACK_TENANT + "' must be set"); } this.pathPrefix = "v1.1/" + tenant + "/"; this.endpoint = (String) this.cloud.getCustom().get(OPENSTACK_OPENSTACK_ENDPOINT); if (this.endpoint == null) { throw new IllegalArgumentException("Custom field '" + OPENSTACK_OPENSTACK_ENDPOINT + "' must be set"); } this.service = client.resource(this.endpoint); this.identityEndpoint = (String) this.cloud.getCustom().get(OPENSTACK_OPENSTACK_IDENTITY_ENDPOINT); if (this.identityEndpoint == null) { throw new IllegalArgumentException("Custom field '" + OPENSTACK_OPENSTACK_IDENTITY_ENDPOINT + "' must be set"); } final String wireLog = (String) this.cloud.getCustom().get( OPENSTACK_WIRE_LOG); if (wireLog != null) { if (Boolean.parseBoolean(wireLog)) { this.client.addFilter(new LoggingFilter(logger)); } } } |
view rawsetConfig.javaThis Gist brought to you by GitHub.
下一步,shell調用cloud driver的startManagementMachines方法,該方法會調用IaaS API(使用API安全設置)來獲取management machines。而後Cloud API會返回一個Machime明細數組對象(org.cloudifysource.esc.driver.provisioning.MachineDetails),這個對象是新分配的每個management machines細節。這些細節將被shell用於鏈接到這些machines,安裝Cloudify management 組件。最後,Cloudify啓動如下Cloudify controller組件:ESM、GSM、LUS各Management Space。它也會啓動web management container和REST API container。
private String createServer(final String token, final CloudTemplate serverTemplate) throws OpenstackException { final String serverName = this.serverNamePrefix + System.currentTimeMillis(); final String securityGroup = getCustomTemplateValue( serverTemplate, OPENSTACK_SECURITYGROUP, null, false); final String keyPairName = getCustomTemplateValue( serverTemplate, OPENSTACK_KEY_PAIR, null, false); // Start the machine! final String json = "{\"server\":{ \"name\":\"" + serverName + "\",\"imageRef\":\"" + serverTemplate.getImageId() + "\",\"flavorRef\":\"" + serverTemplate.getHardwareId() + "\",\"key_name\":\"" + keyPairName + "\",\"security_groups\":[{\"name\":\"" + securityGroup + "\"}]}}"; String serverBootResponse = null; try { serverBootResponse = service.path( this.pathPrefix + "servers").header( "Content-Type", "application/json").header( "X-Auth-Token", token).accept( MediaType.APPLICATION_XML).post( String.class, json); } catch (final UniformInterfaceException e) { throw new OpenstackException(e); } try { // if we are here, the machine started! final Document doc = documentBuilder.parse(new InputSource(new StringReader(serverBootResponse))); final String status = xpath.evaluate( "/server/@status", doc); if (!status.startsWith("BUILD")) { throw new IllegalStateException("Expected server status of BUILD(*), got: " + status); } final String serverId = xpath.evaluate( "/server/@id", doc); return serverId; } catch (XPathExpressionException e) { throw new OpenstackException("Failed to parse XML Response from server. Response was: " + serverBootResponse + ", Error was: " + e.getMessage(), e); } catch (SAXException e) { throw new OpenstackException("Failed to parse XML Response from server. Response was: " + serverBootResponse + ", Error was: " + e.getMessage(), e); } catch (IOException e) { throw new OpenstackException("Failed to send request to server. Response was: " + serverBootResponse + ", Error was: " + e.getMessage(), e); } } |
view rawcreateServer.javaThis Gist brought to you by GitHub.
在這個情節,cloud driver存在於server machine。當controller獲得安裝一個應用的指示時,它將指示cloud driver按recipe描述啓動相應數量的machine。爲了達到此目的,cloud driver首先獲取Admin對象來報告分配應用的machines的公共IP地址和其它詳細信息。Admin對象是經過controller調用setAdmin方法來設置的。
而後,只要有machime須要供應,controller調用cloud driver的startMachine方法,直到全部請求的machines開啓並運行經過LUS註冊的Cloudify agent,或者直到請求超時。
startMachine操做步驟以下:
Driver從configuration Object中定義的的template 的屬性獲取machine信息。
在controller進行宕機補嘗時,或從新平衡服務時,相同的情景會產生,以下圖。
能夠直接插入操做命令,也可指向一個上傳的腳本。
/* example #1 */ SMALL_LINUX : template{ ... /* The following command will be executed after Java and Cloudify are installed, but before Cloudify is started. */ initializationCommand "echo this is an init command" } /* example #2 */ SMALL_LINUX : template{ ... /* The following command will be executed after Java and Cloudify are installed, but before Cloudify is started. In the following example, myscript.sh should be placed in the same folder as the bootstrap-management.sh - (usually the upload folder). */ initializationCommand "chmod +x myscript.sh; ./myscript.sh" } |
view rawinline.groovyThis Gist brought to you by GitHub.
能夠指定如何傳輸文件到遠程機器上: SCP, SFTP or Windows protocol.
SMALL_LINUX : template{ ... /* File transfer mode. Optional, defaults to SCP. */ fileTransfer org.cloudifysource.dsl.cloud.FileTransferModes.CIFS ... } |
view rawfileTransfer.groovyThis Gist brought to you by GitHub.
能夠指定好何執行遠程腳本: SSH or WinRM
SMALL_LINUX : template{ ... /* Remote execution mode. Options, defaults to SSH. */ remoteExecution org.cloudifysource.dsl.cloud.RemoteExecutionModes.WINRM ... } |
view rawremoteExec.groovyThis Gist brought to you by GitHub.
爲了將配置信息傳遞到Cloud Driver,在Cloudify shell提示符中,輸入 :
install-application -cloudConfiguration PATH_TO_CONF PATH_TO_APPLICATION
cloudConfiguration 包括一個路徑(相對或絕對)指向一個文件或目錄,裏面包含用於該應用的cloud driver的配置信息。如如下代碼塊所示:
public void setCustomDataFile(File file) { try { //read text/property file with the service-id (a.k.a deployment-id) Properties props = new Properties(); props.load(new FileInputStream(file)); // Do stuff ... } catch (Exception e) { //log exception } } |
view rawsetCustomDataFile.javaThis Gist brought to you by GitHub.
在此景情下,cloud driver存在於server machine。當controller接收到卸載一個已部署的應用的指示時,它會停掉這個應用的服務,並指示cloud driver卸載掉運行該服務的machines。這是經過調用cloud driver的stopMachine方法實現的,此方法會調用cloud的IaaS API,以指示相應的Cloud中止相關machines。
@Override public boolean stopMachine(final String ip, final long duration, final TimeUnit unit) throws InterruptedException, TimeoutException, CloudProvisioningException { final long endTime = calcEndTimeInMillis( duration, unit); if (isStopRequestRecent(ip)) { return false; } final String token = createAuthenticationToken(); try { terminateServerByIp(ip, token, endTime); return true; } catch (final Exception e) { throw new CloudProvisioningException(e); } } |
view rawstopMachine.javaThis Gist brought to you by GitHub.
如下代碼段爲調用cloud’s IaaS API:
try { service.path( this.pathPrefix + "servers/" + serverId).header( "X-Auth-Token", token).accept( MediaType.APPLICATION_XML).delete(); } catch (final UniformInterfaceException e) { throw new IllegalArgumentException(e); } |
view rawterminateServerAPI.javaThis Gist brought to you by GitHub.
在該情景,cloud driver存在於Client machine。在Cloudify shell 提示符中,用戶運行tear down命令,指定一個cloud driver的實現來卸載management machines。這是通是controller調用cloud driver的stopManagementMachies方法實現的。該方法調用cloud的IaaS API,並指示它中止相關的machines。
@Override public void stopManagementMachines() throws TimeoutException, CloudProvisioningException { final String token = createAuthenticationToken(); final long endTime = calcEndTimeInMillis( DEFAULT_SHUTDOWN_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); List<Node> nodes; try { nodes = listServers(token); } catch (final OpenstackException e) { throw new CloudProvisioningException(e); } final List<String> ids = new LinkedList<String>(); for (final Node node : nodes) { if (node.getName().startsWith( this.serverNamePrefix)) { try { ids.add(node.getId()); } catch (final Exception e) { throw new CloudProvisioningException(e); } } } try { terminateServers( ids, token, endTime); } catch (final TimeoutException e) { throw e; } catch (final Exception e) { throw new CloudProvisioningException("Failed to shut down managememnt machines", e); } } |
view rawstopManagement.javaThis Gist brought to you by GitHub.