PaaS-TA-5.5.0
Search…
ServicePack 개발 가이드

1. 개요

1.1. 문서 개요

1.1.1. 목적

본 문서(서비스팩 가이드)는 전자정부표준프레임워크 기반의 Open PaaS 프로젝트의 서비스팩개발 및 운영시 품질목표를 달성하기 위하여 적용되어야 할 각종 표준 및 척도를 정의할 수 있도록 가이드로 제시하는 문서이다. 이 개발 표준 가이드를 근거로 하여 개발시스템의 품질을 높이고, 서비스팩 개발자들이 상호간의 소스코드에 대한 가독성 및 이해도를 높이며, 해당 표준에 따라 개발함으로써 프로젝트 품질의 일관성을 유지하여 프로젝트 완료 이후의 원활한 시스템 유지보수를 지원할 수 있도록 하는데 그 목적이 있다.

1.1.2. 범위

본 문서의 범위는 전자정부표준프레임워크 기반의 Open PaaS 프로젝트의 서비스팩개발에 대한 내용으로 한정되어 있다.

1.1.3. 참고 자료

2. Service Broker API 개발 가이드

2.1. 개요

개방형 클라우드 플랫폼 Service API는 Cloud Controller와 Service Broker 사이의 규약을 정의한다. Broker는 HTTP (or HTTPS) endpoints URI 형식으로 구현된다. 하나 이상의 Service가 하나의 Broker 에 의해 제공 될 수 있고, 로드 밸런싱이 가능하게 수평 확장성 있게 제공 될 수 있다.

2.2. Service Architecture

Services 는 Service Broker API 라고 불리우는 cloud controller 클라이언트 API를 구현하여 개방형 클라우드 플랫폼에서 사용된다. Services API는 독립적인 cloud controller API의 버전이다. 이는 플랫폼에서 외부 application을 이용 가능하게 한다. (database, message queue, rest endpoint , etc)

2.3. Service Broker API Architecture

개방형 클라우드 플랫폼 Service API는 Cloud Controller 와 Service Broker 사이의 규약 (catalog, provision, deprovision, update provision plan, bind, unbind)이고 Service Broker 는 RESTful API 로 구현하고 Cloud Controller 에 등록한다.

2.4. Pivotal(Cloud Foundry) Marketplace Model

AppDirect: 클라우드 서비스 marketplace 및 관리 솔루션의 선두 업체이고 많은 글로벌 회사의 marketplace를 구축하였다. (삼성, Cloud Foundry, ETC) AppDirect는 Cloud Foundry 서비스 중개(brokerage) 기능과 부가 서비스를 제공한다. Service Provider 및 Cloud Foundry 통합에 관련 설명

2.5. 개발 가이드

서비스의 구현 방법은 서비스 제공자(Provider) 와 개발자(developer)의 몫이다. 개방형 클라우드 플랫폼은 서비스 제공자가 6가지의 Service Broker API를 구현해야 한다. 이때 2.4 Pivotal Marketplace Model를 이용해서 AppDirect 에서 제공중인 서비스 제공자와 협의 하여 AppDirect 의 중개 기능을 이용해서 제공할수도 있다. 또한 Broker 는 별도의 애플리케이션으로 구현하든지 기존 서비스에 필요한 HTTP endpoint를 추가함으로써 구현 될 수 있다.
본 개발 가이드는 Service Broker 에서 service back-end를 제어하는 방식을 가이드 한다.AppDirect를 사용하는 경우에는 http://go.appdirect.com/request-more-information를 참고하여 개발한다.
Service Broker는 6개의 기본 API 기능이 필요하다. (상세 설명은 각 API 가이드 참고)
Service Broker API의 두 가지 주요 버전은 현재 개방형 클라우드 플랫폼 v1 및 v2를 지원한다. v1은 사용 되지 않으며 개방형 클라우드 플랫폼의 다음 버전에서 제거 될 수 있으니 Service Broker는 v2로 구현하는 것을 권장한다.
  • 버전 정보 (가이드 문서는 2.5 버전을 기준으로 작성함)
  • 인증
Cloud Controller 는 모든 요청에 HTTP 기본 인증(인증 헤더)을 사용하여 Broker와 인증하여 사용자 이름과 암호를 포함하지 않는 모든 Broker 등록을 거부한다. Broker는 사용자 이름과 암호를 확인하고 자격 증명이 유효하지 않은 경우 401 Unauthorized 메시지를 반환 한다. Cloud Controller에서 추가 보안이 요구되는 경우 SSL을 사용하여 브로커에 접속 지원을 한다.

2.5.1. Catalog API 가이드

서비스 Catalog는 서비스 및 서비스 Plan의 정보를 조회한다. Cloud Controller는 처음에 모든 Broker에서 endpoint를 취득해서 Cloud Controller 데이터베이스에 저장되어 있는 user-facing service catalog를 조회한다. 또한 Cloud Controller는 Broker가 업데이트 될 때 마다 catalog를 업데이트한다.Catalog API를 구현하면 CF CLI를 통해서 Service Broker를 등록 할 수 있다.
  1. 1.
    Request
1.1. Route
1
GET /v2/catalog
Copied!
1.2. cURL
1
curl -H "X-Broker-API-Version: 2.4" http://username:[email protected]/v2/catalog
2
예)
3
curl -H "X-Broker-API-Version: 2.4" http://admin:[email protected]/v2/catalog
Copied!
  1. 1.
    Response
2.1. Status Code
2.2. Body (* 필드는 필수)
2.3. Service Metadata
2.4. Plan Metadata
2.5. Quota Plan
◎ sample body response message
1
{
2
"services": [
3
{
4
"id": "44b26033-1f54-4087-b7bc-da9652c2a539",
5
"name": "p-mysql",
6
"description": "A MySQL service for application development and testing",
7
"tags": [
8
"mysql"
9
],
10
"metadata": {
11
"displayName": "MySQL for Pivotal CF",
12
"imageUrl": "data:image/png;base64,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",
13
"longDescription": "Provisioning a service instance creates a MySQL database. Binding applications to the instance creates unique credentials for each application to access the database.",
14
"providerDisplayName": "Pivotal Software",
15
"documentationUrl": "http://docs.gopivotal.com/",
16
"supportUrl": "http://gopivotal.com/support/"
17
},
18
"plans": [
19
{
20
"id": "ab08f1bc-e6fc-4b56-a767-ee0fea6e3f20",
21
"name": "100mb-dev",
22
"description": "Shared MySQL Server",
23
"metadata": {
24
"costs": [
25
{
26
"amount": {
27
"usd": 0
28
},
29
"unit": "MONTH"
30
}
31
],
32
"bullets": [
33
"Not for production use - server is not replicated",
34
"Shared MySQL server",
35
"100 MB storage",
36
"40 concurrent connections"
37
],
38
"displayName": "(( merge || \"100 MB Dev\" ))"
39
}
40
}
41
],
42
"bindable": true,
43
"dashboard_client": {
44
"id": "p-mysql",
45
"secret": "eaa139af583c",
46
"redirect_uri": "http://10.30.40.61/"
47
}
48
}
49
]
50
}
Copied!
  1. 1.
    Catalog Rest API 구현
3.1. JAVA 방식
1
-- CatalogRestController.java (Spring 프레임워크 사용)
2
3
@Controller
4
@RequestMapping("/v2/catalog") // Spring 어노테이션을 사용
5
class CatalogRestController {
6
def settings;
7
8
@RequestMapping(method=RequestMethod.GET)
9
@ResponseBody
10
synchronized Map getCatalog() {
11
if (!settings) {
12
Yaml yaml = new Yaml();
13
// settings.yml 파일 안에 서비스 정보와 plan 정보가 들어 있음
14
settings = yaml.load(this.class.getClassLoader().getResourceAsStream("settings.yml"));
15
}
16
17
return settings;
18
}
19
20
}
21
22
-- settings.yml 파일
23
24
services:
25
- name: p-mysql
26
id: 3101b971-1044-4816-a7ac-9ded2e028079
27
description: MySQL service for application development and testing
28
tags:
29
- mysql
30
- relational
31
max_db_per_node: 250
32
metadata:
33
provider:
34
name:
35
listing:
36
imageUrl: ~
37
blurb: MySQL service for application development and testing
38
plans:
39
- name: 5mb
40
id: 2451fa22-df16-4c10-ba6e-1f682d3dcdc9
41
description: Shared MySQL Server, 5mb persistent disk, 40 max concurrent connections
42
max_storage_mb: 5 # in MB
43
metadata:
44
cost: 0.0
45
bullets:
46
- content: Shared MySQL server
47
- content: 5 MB storage
48
- content: 40 concurrent connections
Copied!
3.2. Ruby 방식(Ruby on Rails)
1
-- 어플리케이션을 만들 때 레일즈(rails)을 이용 해서 새로운 어플리케이션을 위한 기본 생성 구조를 만든다. 아래 표 참고
2
$ rails new<broker_name>
3
>![openpaas-servicepack-13]
4
5
-- config/routes.rb : posts 를 위한 라우팅 정보를 담은 수정된 라우팅 파일
6
7
CfMysqlBroker::Application.routes.draw do
8
resource :preview, only: [:show]
9
10
namespace :v2 do
11
resource :catalog, only: [:show] // 접속 라우팅 설정 (V2/catalog)
12
patch 'service_instances/:id' => 'service_instances#set_plan'
13
resources :service_instances, only: [:update, :destroy] do
14
resources :service_bindings, only: [:update, :destroy]
15
end
16
end
17
18
end
19
20
-- RestController 구현 (app/controllers/v2/catalogs_controller.rb)
21
22
class V2::CatalogsController < V2::BaseController
23
def show
24
render json: {
25
services: services.map {|service| service.to_hash }
26
}
27
end
28
29
private
30
31
def services
32
(Settings['services'] || []).map {|attrs| Service.build(attrs)}
33
end
34
end
Copied!
3.3. Node.js 방식
1
-- express 라는 Node.js 에서 가장 많이 사용하는 웹 프레임워크 모듈을 이용해서 Rest API 를 만든다.
2
3
# sample (app.js)
4
5
var express = require('express')
6
, http = require('http')
7
, app = express()
8
, server = http.createServer(app);
9
10
app.get('/v2/catalog ', function (req, res) {
11
// catalog 기능 구현
12
});
13
14
server.listen(8000, function() { // 포트 설정
15
console.log('Express server listening on port ' + server.address().port);
16
});
Copied!
  1. 1.
    서비스 별 Catalog API 개발 명세
    Catalog API 경우에는 서비스의 종류와 관계없이 Service 및 Plan 정보를 저장되어 있는 settings.yml 파일이나 기타 메타 파일 또는 소스 안에 정보를 저장한 후 제공한다. 만일 AppDirect 를 이용하는 경우는 Catalog 정보를 조회해오는 AppDirect API를 호출하여 그 결과를 제공한다. 샘플 settings.yml 파일은 3. Catalog Rest API 구현 참고.
◎ Pivotal 서비스 Plan 예시
◎ Pivotal 서비스 Dashboard 예시

2.5.2. Provision API 가이드

Broker가 Cloud Controller로 부터 provision 요구를 수신하면 개발자를 위한 새로운 서비스 인스턴스를 생성한다. provision 시 서비스들의 종류에 따라 provision 결과는 다르다. Mysql DataBase 인 경우에는 새로운 DATABASE 스키마를 생성한다. 또한 non-data 서비스 인 경우의 provision은 기존 시스템에 계정을 얻는 의미 일 수도 있다. 자세한 내용은 아래에 각 서비스별 provision을 참고한다.
  1. 1.
    Request
1.1. Route
1
PUT /v2/service_instances/:instance_id
Copied!
참고: 서비스 인스턴스의 instance_id는 Cloud Controller에 의해 제공된다. 이 ID는 인스턴스 삭제, 바인드 및 바인드 해지에 사용된다.
1.2. cURL $ curl http://username:[email protected]/v2/service_instances/:instance_id -d '{ "service_id": "service-guid-here", "plan_id": "plan-guid-here", "organization_guid": "org-guid-here", "space_guid": "space-guid-here" }' -X PUT -H "X-Broker-API-Version: 2.4" -H "Content-Type: application/json"
1.3. Body
  1. 1.
    Response
    2.1. Status Code
    1]
2.2. Body 모든 응답 bodies 는 JSON Object ({}) 형식으로 한다.
2.3. Dashboard Single Sign-On. Single Sign-On (SSO)는 개방형 클라우드 플랫폼 사용자들이 개방형 클라우드 플랫폼 자격 증명을 사용하여 third-party 서비스의 대시 보드에 접근한다. 서비스 대시 보드는 서비스가 제공하는 기능의 일부 또는 전부를 사용할 수 있는 웹 인터페이스이다. SSO는 반복되는 로그인과 여러 서비스의 계정을 통합 관리한다. OAuth2 프로토콜 인증을 처리하기 때문에 사용자의 자격 증명은 직접 서비스로 전송하지 않는다. SSO 기능을 사용하려면 Cloud Controller UAA client 에 서비스 브로커의 생성 및 삭제 할 수 있는 권한이 있어야 한다. 이 클라이언트는 개방형 클라우드 플랫폼 설치시 구성한다. (설치 문서 참고)
◎ CF 설치시 Dashboard SSO 설정 예)
1
properties:
2
uaa:
3
clients:
4
cc-service-dashboards:
5
secret: cc-broker-secret
6
scope: openid,cloud_controller_service_permissions.read
7
authorities: clients.read,clients.write,clients.admin
8
authorized-grant-types: client_credentials
Copied!
  1. 1.
    Provision Rest API 구현 3.1. JAVA 방식
    -- ServiceInstanceRestController.java (Spring 프레임워크 사용)
    @Controller @RequestMapping("/v2/service_instances/{id}") class ServiceInstanceRestController { @Autowired private ServiceInstanceService service;
    @RequestMapping(method = RequestMethod.PUT) @ResponseBody Map update(@PathVariable String id) { ServiceInstance instance = service.findById(id); // Spring 프레임워크 사용으로 서비스 구현 if (!service.isExists(instance)) { service.create(instance); // 서비스 인스턴스를 생성하는 부분 (개발 명세 내용 구현) } return [:];
    } }
3.2. Ruby 방식(Ruby on Rails)
1
-- config/routes.rb : 라우팅 정보를 담은 파일
2
3
CfMysqlBroker::Application.routes.draw do
4
resource :preview, only: [:show]
5
6
namespace :v2 do
7
resource :catalog, only: [:show] // 접속 라우팅 설정 (V2/catalog)
8
patch 'service_instances/:id' => 'service_instances#set_plan'
9
resources :service_instances, only: [:update, :destroy] do
10
resources :service_bindings, only: [:update, :destroy]
11
end
12
end
13
14
end
15
16
-- RestController 구현 (app/controllers/v2/service_instances_controller.rb)
17
18
class V2::ServiceInstancesController < V2::BaseController
19
20
# This is actually the create
21
def update
22
// 서비스 instance 생성 기능 구현 (개발 명세 내용 구현)
23
end
24
25
end
Copied!
3.3. Node.js 방식
1
◎ sample (app.js) : Catalog API 참고
2
3
var router = express.Router();
4
5
router.route('/v2/service_instances/:id’)
6
7
.put(function(req, res, next) {
8
// 서비스 instance 생성 기능 구현 (개발 명세 내용 구현)
9
10
})
Copied!
  1. 1.
    서비스 별 Provision API 개발 명세
  2. 2.
    인스턴스 생성시 unique 한 이름으로 만든다.
  3. 3.
    생성 요청한 인스턴스 ID 가 이미 존재 하는지 체크한다.
  4. 4.
    선택 한 plan 정보로 인스턴스가 생성 가능한지 체크 하고 가능할 경우 해당 인스턴스를 만든다.
  5. 5.
    인스턴스 생성이 완료 되면 위에서 기술된 JSON Object 형식으로 Cloud Controller 에 전송한다.
4.1. RDBMS
  1. 1.
    Mysql 경우
    • 생성할 데이터 베이스가 존재 하는지 체크 SHOW DATABASES LIKE '${instance.database}'
    • 새로운 데이터 베이스 생성 CREATE DATABASE IF NOT EXISTS ${instance.database}
    • 생성 후 Dashboard 정보를 JSON Object 형식으로 Cloud Controller 에 전송.
  2. 2.
    Cubrid DB 경우
    • 데이터 베이스 생성할 디렉토리 생성 및 이동 $ mkdir $ cd
    • 데이터 베이스 생성 $ cubrid created--db-volume-size=100M --log-volume-size=100M en_US
    • 데이터 베이스 실행 $ cubrid service start $ cubrid server start
4.2. 대용량 저장소 1. GlusterFS 경우 ◎ GlusterFS 로 파일을 업로드 하기 위해서는 먼저 GlusterFS 와 OpenStack swift 로 service back-end로 구성하여 Object Storage 방식으로 파일을 업로드 다운로드를 할수 있게 제공한다. (아마존 S3 방식과 유사)
  • 새로운 Swift Account 를 생성
    Method : PUT
    Req URL : http(s)://[IP Address OR HostName]/auth/v2/[AccountID]
    Header : X-Auth-Admin-User: .super_admin X-Auth-Admin-Key: swauthkey X-Account-Meta-Quota-Bytes: [Size(Byte)]
4.3. NoSQL DB 1. mongoDB 경우
  • 새로운 데이터 베이스를 생성
    use switched to db

2.5.3. Update Instance API 가이드

Update Instance API는 기존의 서비스 인스턴스의 plan를 수정 한다. 즉 서비스 인스턴스의 plan을 업그레이드나 다운그레이드 한다. 이 기능을 사용하려면 브로커는 카탈로그 endpoint 에서 “plan_updateable: true”설정 해주어야 한다. 이 옵션 필드가 포함되어 있지 않은 경우에는 service plan 변경 요청에 대해 의미 있는 오류를 반환하고 브로커는 API 호출을 하지 않는다. 이 필드가 포함된 경우 개방형 클라우드 플랫폼의 모든 plan 변경 요청에 브로커로 API 호출을 수행하며 브로커에서는 plan 지원 여부를 확인한다.
  1. 1.
    Request
    1.1. Route
    PATCH /v2/service_instances/:instance_id
참고: instance_id는 이전에 provision 서비스 인스턴스의 GUID
1.2. cURL $ curl http://username:[email protected]/v2/service_instances/:instance_id -d '{ "plan_id": "plan-guid-here" }' -X PATCH -H "X-Broker-API-Version: 2.4" -H "Content-Type: application/json"
1.3. Body
  1. 1.
    Response
    2.1. Status Code
    STATUS CODE DESCRIPTION
2.2. Body 모든 응답 bodies 는 JSON Object ({}) 형식으로 한다.
  1. 1.
    Update Service instance Rest API 구현 3.1. JAVA 방식 -- ServiceInstanceRestController.java (Spring 프레임워크 사용)
    @Controller @RequestMapping("/v2/service_instances/{id}") class ServiceInstanceRestController { @Autowired private ServiceInstanceService service;
    @RequestMapping(method = RequestMethod.PATCH) @ResponseBody Map updateInstance(@PathVariable String id) { ServiceInstance instance = service.findById(id); // Spring 프레임워크 사용으로 서비스 구현 if (!service.isExists(instance)) { service.update(instance); // 서비스 인스턴스를 정보 수정하는 부분 (개발 명세 내용 구현) } return [:];
    } }
3.2. Ruby 방식(Ruby on Rails) -- config/routes.rb : posts 를 위한 라우팅 정보를 담은 수정된 라우팅 파일
1
CfMysqlBroker::Application.routes.draw do
2
resource :preview, only: [:show]
3
4
namespace :v2 do
5
resource :catalog, only: [:show] // 접속 라우팅 설정 (V2/catalog)
6
patch 'service_instances/:id' => 'service_instances#set_plan'
7
resources :service_instances, only: [:update, :destroy] do
8
resources :service_bindings, only: [:update, :destroy]
9
end
10
end
11
12
end
13
14
-- RestController 구현 (app/controllers/v2/service_instances_controller.rb)
15
16
class V2::ServiceInstancesController < V2::BaseController
17
18
def set_plan
19
// 서비스 인스턴스 plan 정보 업데이트
20
end
21
22
end
Copied!
3.3. Node.js 방식 ◎ sample (app.js) : Catalog API 참고
1
var router = express.Router();
2
3
router.route('/v2/service_instances/:id’)
4
5
.patch(function(req, res, next) {
6
// 서비스 instance 수정 기능 구현 (개발 명세 내용 구현)
7
8
})
Copied!
  1. 1.
    서비스 별 Update Service instance API 개발 명세 4.1. 공통 1. 현재 제공 중인 plan 정보와 변경 요청 받은 plan 정보가 다른지 체크한다.
    1. 1.
      다운 그레이드 할 경우 이미 사용하는 용량이 다운 그레이드 할 용량보다 클 경우 에러를 발생시킨다.
    2. 2.
      업 그레이드 할 경우 plan 정보를 업데이트 한다. (예: DBMS 서비스 경우 connection 수, storage 용량)
    3. 3.
      변경된 내용을 Cloud Controller 전달 한다.

2.5.4. Deprovision API 가이드

브로커가 개방형 클라우드 플랫폼으로부터 deprovision 요청을 수신 할 때 provision 생성시 제공했던 모든 리소스를 삭제한다.
  1. 1.
    Request
    1.1. Route
    DELETE /v2/service_instances/:instance_id
1.2. Parameters
1.3. cURL $ curl 'http://username:[email protected]/v2/service_instances/:instance_id?service_id= service-id-here&plan_id=plan-id-here' -X DELETE -H "X-Broker-API-Version: 2.4"
  1. 1.
    Response
    2.1. Status Code
2.2. Body 모든 응답 bodies 는 JSON Object ({}) 형식으로 한다. 성공시 “{}” 값을 전송받는다.
  1. 1.
    Deprovision Rest API 구현 3.1. JAVA 방식 -- ServiceInstanceRestController.java (Spring 프레임워크 사용)
    @Controller @RequestMapping("/v2/service_instances/{id}") class ServiceInstanceRestController { @Autowired private ServiceInstanceService service;
    @RequestMapping(method = RequestMethod.DELETE) @ResponseBody Map destroy(@PathVariable String id) { ServiceInstance instance = service.findById(id); if (service.isExists(instance)) { service.delete(instance); // 서비스 instance 삭제 기능 구현 (개발 명세 내용 구현) } return [:] } }
3.2. Ruby 방식(Ruby on Rails) -- config/routes.rb : posts 를 위한 라우팅 정보를 담은 수정된 라우팅 파일
1
CfMysqlBroker::Application.routes.draw do
2
resource :preview, only: [:show]
3
4
namespace :v2 do
5
resource :catalog, only: [:show] // 접속 라우팅 설정 (V2/catalog)
6
patch 'service_instances/:id' => 'service_instances#set_plan'
7
resources :service_instances, only: [:update, :destroy] do
8
resources :service_bindings, only: [:update, :destroy]
9
end
10
end
11
12
end
13
14
-- RestController 구현 (app/controllers/v2/service_instances_controller.rb)
15
16
class V2::ServiceInstancesController < V2::BaseController
17
18
def destroy
19
// 서비스 instance 삭제 기능 구현 (개발 명세 내용 구현)
20
end
21
22
end
Copied!
3.3. Node.js 방식 ◎ sample (app.js) : Catalog API 참고
1
var router = express.Router();
2
3
router.route('/v2/service_instances/:id’)
4
5
.delete(function(req, res, next) {
6
// 서비스 instance 삭제 기능 구현 (개발 명세 내용 구현)
7
8
})
Copied!
  1. 1.
    서비스 별 Deprovision API 개발 명세
  2. 2.
    삭제 요청하는 서비스 인스턴스가 존재 하는지 체크한다.
  3. 3.
    인스턴스가 존재 하면 삭제할 인스턴스에 Application 이 bind 되어 있는지 체크 한다.
  4. 4.
    만일 bind 되어 있는 Application 이 존재 할 경우 Error 를 Cloud Controller 에 전송한다.
  5. 5.
    bind 되어 있는 Application 이 존재 하지 않을 경우 해당 서비스 인스턴스를 삭제한다.
4.1. RDBMS 1. Mysql 경우
  • 데이터 베이스 삭제 DROP DATABASE IF EXISTS #{connection.quote_table_name(database_name)}
  • Cubrid DB 경우
  • 서비스 종료 후 데이터베이스 제거 $ cubrid service stop $ cubrid deletedb
  • 제거한 데이터베이스 디렉터리 제거 $ rm –rf /
4.2. 대용량 저장소 1. GlusterFS 경우
  • Swift Account 를 삭제
    Method : DELETE
    Req URL : http(s)://[IP Address OR HostName]/auth/v2/[AccountID]
    Header : X-Auth-Admin-User: .super_admin X-Auth-Admin-Key: swauthkey
4.3. NoSQL DB 1. mongoDB 경우
  • 데이터 베이스 삭제
    use switched to db db.dropDatabase() { "dropped" : "", "ok" : 1 }

2.5.5. Bind API 가이드

Provision만으로 서비스를 사용할 수 있을 경우에는 bind 기능 구현은 필요 없고 결과 성공 메시지만 개방형 클라우드 플랫폼에 전송하면 된다. 브로커가 개방형 클라우드 플랫폼으로부터 바인딩 요청을 수신 할 때 프로비저닝 된 자원을 활용하는데 필요한 정보를 반환한다. 해당 정보는 credentials(자격증명)안에 제공된다. Applicatoin에 고유한 credentials(자격증명)을 발급하여다른 Application에는 영향을 주어서는 안된다.
  1. 1.
    Request
    1.1. Route
    PUT /v2/service_instances/:instance_id/service_bindings/:binding_id
    참고: binding_id는 서비스 바인딩을 하기 위해 Cloud Controller에 의해 제공된다. binding_id는 향후 바인딩 해제 요청에 사용된다.
1.2. cURL $ curl http://username:[email protected]/v2/service_instances/ :instance_id/service_bindings/:binding_id -d '{ "plan_id": "plan-guid-here", "service_id": "service-guid-here", "app_guid": "app-guid-here" }' -X PUT -H "X-Broker-API-Version: 2.4" -H "Content-Type: application/json"
1.3. Body
  1. 1.
    Response
    2.1. Status Code
    다른 상태코드(Status Code) 응답은 실패를 의미한다.
2.2. Body
2.3. Binding Credentials 서비스 바인딩 경우 바인드 API 호출에 응답하여 사용자가 Application에서 사용 할 수있는 인증 정보를 반환한다. 개방형 클라우드 플랫폼 환경 변수 VCAP_SERVICES에 이러한 자격 증명을 제공한다. 가능하면 credentials(자격증명) 필드 목록에서 사용하기를 권장한다. 필요에 따라 추가 필드를 제공 할 수 있지만 제공되는 필드로 사용자의 요구 사항을 충족하는 경우 해당 필드를 사용한다.
중요: 연결 문자열(connection string)을 지원하는 서비스를 제공하는 경우 적어도 uri 키를 제공해야한다.위에서 언급 한 바와 같이 또한 별도의 자격 증명 필드를 제공 할 수있다. Buildpacks 및 Application 라이브러리는 uri 키를 사용한다.
◎ Example VCAP_SERVICES 결과
1
VCAP_SERVICES=
2
{
3
cleardb: [
4
{
5
name: "cleardb-1",
6
label: "cleardb",
7
plan: "spark",
8
credentials: {
9
name: "ad_c6f4446532610ab",
10
hostname: "us-cdbr-east-03.cleardb.com",
11
port: "3306",
12
username: "b5d435f40dd2b2",
13
password: "ebfc00ac",
14
uri: "mysql://b5d435f40dd2b2:[email protected]:3306/ad_c6f4446532610ab",
15
jdbcUrl: "jdbc:mysql://b5d435f40dd2b2:[email protected]:3306/ad_c6f4446532610ab"
16
}
17
}
18
],
19
cloudamqp: [
20
{
21
name: "cloudamqp-6",
22
label: "cloudamqp",
23
plan: "lemur",
24
credentials: {
25
uri: "amqp://ksvyjmiv:[email protected]/ksvyjmiv"
26
}
27
}
28
{
29
name: "cloudamqp-9dbc6",
30
label: "cloudamqp",
31
plan: "lemur",
32
credentials: {
33
uri: "amqp://vhuklnxa:[email protected]/vhuklnxa"
34
}
35
}
36
],
37
rediscloud: [
38
{
39
name: "rediscloud-1",
40
label: "rediscloud",
41
plan: "20mb",
42
credentials: {
43
port: "6379",
44
host: "pub-redis-6379.us-east-1-2.3.ec2.redislabs.com",
45
password: "1M5zd3QfWi9nUyya"
46
}
47
},
48
],
49
}
Copied!
2.4. Application Log Streaming 개방형 클라우드 플랫폼은 서비스 인스턴스에 바인딩 된 Application에 대한 로그를 스트리밍 한다. 서비스 인스턴스에 바인딩 된 모든 Application에 대한 로그는 해당 인스턴스로 스트리밍된다.
동작하는 방법은 아래와 같다. 1. 브로커는 바인드에 대한 응답으로 syslog_drain_url에 대한 값을 반환한다. 2. Application이 재구동 할 때 VCAP_SERVICES 안의 syslog_drain_url 의 key와 value 를 갱신한다. 3. DEAs는 지속적으로 Loggregator에서 Application 로그를 스트리밍한다. 4. VCAP_SERVICES 안에 syslog_drain_url이 존재하면 DEA는 그 로그에 그 필드를 태그한다. 5. Loggregator는 값으로 지정된 위치에 이 key를 태그하여 로그 스트리밍한다.
  1. 1.
    Bind Rest API 구현 3.1. JAVA 방식 -- ServiceBindingRestController.java (Spring 프레임워크 사용)
    @Controller @RequestMapping("/v2/service_instances/{instanceId}/service_bindings/{bindingId}") class ServiceBindingRestController { @Autowired ServiceBindingService bindingService;
    @RequestMapping(method = RequestMethod.PUT) @ResponseBody ServiceBinding update(@PathVariable String instanceId, @PathVariable String bindingId) { ServiceBinding binding = bindingService.findById(bindingId, instanceId); bindingService.save(binding); // 서비스 바인드 기능 구현 (개발 명세 내용 구현) return binding; }
    }
3.2. Ruby 방식(Ruby on Rails) -- config/routes.rb : posts 를 위한 라우팅 정보를 담은 수정된 라우팅 파일
1
CfMysqlBroker::Application.routes.draw do
2
resource :preview, only: [:show]
3
4
namespace :v2 do
5
resource :catalog, only: [:show] // 접속 라우팅 설정 (V2/catalog)
6
patch 'service_instances/:id' => 'service_instances#set_plan'
7
resources :service_instances, only: [:update, :destroy] do
8
resources :service_bindings, only: [:update, :destroy]
9
end
10
end
11
12
end
13
14
-- RestController 구현 (app/controllers/v2/service_bindings_controller.rb)
15
16
class V2::ServiceBindingsController< V2::BaseController
17
18
def update
19
// 서비스 bind 기능 구현 (개발 명세 내용 구현)
20
end
21
22
end
Copied!
3.3. Node.js 방식 ◎ sample (app.js) : Catalog API 참고
1
var router = express.Router();
2
3
router.route('/v2/service_instances/:instanceId/service_bindings/:bindingId’)
4
5
.put(function(req, res, next) {
6
// 서비스 bind 기능 구현 (개발 명세 내용 구현)
7
8
})
Copied!
  1. 1.
    서비스 별 Bind API 개발 명세
  2. 2.
    Bind 할 서비스 인스턴스가 존재 하는지 체크 한다.
  3. 3.
    Application 에 bind 할 정보를 생성하여 Application 에 전달한다.
  4. 4.
    이때 bind 정보는 랜덤하게 생성하고 base64 인코딩해서 보낸다.
4.1. RDBMS 1. Mysql 경우
  • 데이터 베이스에 접속할 사용자를 생성한다. CREATE USER #{username} IDENTIFIED BY #{password}
  • provision 시 생성한 데이터 베이스에 생성한 사용자가 사용 가능하게 권한을 주고 plan에 해당하는 connection 수를 제공한다.
    GRANT ALL PRIVILEGES ON #{databasename}.* TO #{username}@'%'WITH MAX_USER_CONNECTIONS #{max_user_connections}
  • 서버에 권한 테이블을 재배치한다. FLUSH PRIVILEGES
  1. 1.
    Cubrid DB 경우
    • 데이터 베이스에 접속할 사용자를 생성한다.
      CREATE USER #{username};
참고: Cubrid DB에서 권한 부여의 최소 단위는 테이블이다. 자신이 만든 테이블은 모든 접근을 허용한다.
4.2. 대용량 저장소 1. GlusterFS 경우
  • 새로운 Swift User 를 생성
    Method : PUT
    Req URL : http(s)://[IP Address OR HostName]:[PORT]/auth/v2/[AccountID]/[UserId]
    Header : X-Auth-Admin-User: .super_admin X-Auth-Admin-Key: swauthkey X-Auth-User-Key: [Password] X-Auth-User-Admin: [true OR false]
4.3. NoSQL DB 1. mongoDB 경우
  • 데이터 베이스에 접속할 사용자를 생성하고 접근 role(read, Write)을 부여한다.
    use switched to db db.getSiblingDB("").runCommand( { createUser: "", pwd: "", roles: [ "readWrite" ] } )

2.5.6. Unbind API 가이드

참고: 바인딩 서비스를 제공하지 않는 브로커는 Unbind API를 구현할 필요가 없다. 브로커가 개방형 클라우드 플랫폼으로부터 unbind 요청을 받으면 바인드(bind)에서 만든 모든 자원(resource)을 삭제한다. 삭제 되면 service에 접근 할수 없다.
  1. 1.
    Request
    1.1. Route
    DELETE /v2/service_instances/:instance_id/service_bindings/:binding_id
1.2. Parameters
1.3. cURL $ curl 'http://username:[email protected]/v2/service_instances/:instance_id/ service_bindings/:binding_id?service_id=service-id-here&plan_id=plan-id-here' -X DELETE -H "X-Broker-API-Version: 2.4"
  1. 1.
    Response
    2.1. Status Code
2.2. Body 모든 응답 bodies 는 JSON Object ({}) 형식으로 한다. 성공시 “{}” 값을 전송받는다.
  1. 1.
    Unbind Rest API 구현 3.1. JAVA 방식 -- ServiceBindingRestController.java (Spring 프레임워크 사용)
    @Controller @RequestMapping("/v2/service_instances/{instanceId}/service_bindings/{bindingId}") class ServiceBindingRestController { @Autowired ServiceBindingService bindingService;
    @RequestMapping(method = RequestMethod.DELETE) @ResponseBody Map destroy(@PathVariable String instanceId, @PathVariable String bindingId) { ServiceBinding binding = bindingService.findById(bindingId, instanceId); bindingService.destroy(binding); // 서비스 unbind 기능 구현 (개발 명세 내용 구현) return [:]; } }
3.2. Ruby 방식(Ruby on Rails) -- config/routes.rb : posts 를 위한 라우팅 정보를 담은 수정된 라우팅 파일
1
CfMysqlBroker::Application.routes.draw do
2
resource :preview, only: [:show]
3
4
namespace :v2 do
5
resource :catalog, only: [:show] // 접속 라우팅 설정 (V2/catalog)
6
patch 'service_instances/:id' => 'service_instances#set_plan'
7
resources :service_instances, only: [:update, :destroy] do
8
resources :service_bindings, only: [:update, :destroy]
9
end
10
end
11
12
end
13
14
-- RestController 구현 (app/controllers/v2/service_bindings_controller.rb)
15
16
class V2::ServiceBindingsController< V2::BaseController
17
18
def destroy
19
// 서비스 unbind 기능 구현 (개발 명세 내용 구현)
20
end
21
22
end
Copied!
3.3. Node.js 방식 ◎ sample (app.js): Catalog API 참고
1
var router = express.Router();
2
3
router.route('/v2/service_instances/:instanceId/service_bindings/:bindingId’)
4
5
.delete(function(req, res, next) {
6
// 서비스 unbind 기능 구현 (개발 명세 내용 구현)
7
8
})
Copied!
  1. 1.
    서비스 별 Unbind API 개발 명세
  2. 2.
    Unbind 할 bind 인스턴스가 존재 하는지 체크 한다.
  3. 3.
    Application 에 bind 된 정보를 삭제하고 결과를 Application 에 전달한다.
4.1. RDBMS 1. Mysql 경우
  • unbind 할 사용자가 존재 하는지 체크 SHOW GRANTS FOR #{username)}
  • 생성된 사용자를 삭제한다. DROP USER #{username}
  • 서버에 권한 테이블을 재배치한다. FLUSH PRIVILEGES
  1. 1.
    Cubrid DB 경우
    • bind 시 생성한 사용자를 삭제한다.
      DROP USER #{username};
4.2. 대용량 저장소 1. GlusterFS 경우
  • Swift User 를 삭제
    Method : DELETE
    Req URL : http(s)://[IP Address OR HostName]/auth/v2/[AccountID]/[UserId]
    Header : X-Auth-Admin-User: .super_admin X-Auth-Admin-Key: swauthkey X-Auth-User-Key: [Password] X-Auth-User-Admin: [true OR false]
4.3. NoSQL DB 1. mongoDB 경우
  • bind 시 생성한 사용자를 삭제한다.
    use switched to db db.runCommand( { dropUser: "" } )

3. Service release 개발 가이드

3.1. 개요

BOSH release 는 jobs(packages 구동 스크립트, monit 스크립트 등), packages, 소스 코드 및 관련 자료의 메타 데이터로 구성되어 있다.BOSH를 통해서 소프트웨어(service back-end, broker 및 etc)를 설치한다. 패키징에 필요한 바이너리 파일 (일명 "blobs")은 release 저장소 내부에 보관하는 필요성을 없애고 release 내 Blob 저장소에 저장되어 외부에서 참조 할 수있다.또한 BOSH release를 활용하기 위해 release yml 를 작성 한다.
참고: service back-end (서비스 provider 가 제공하는 소프트웨어: 2.2 Service Architecture 참고) 가 외부 서비스로 이미 제공하는 provider 인 경우에는 BOSH release 로 service back-end 를 설치할 필요는 없고 해당 브로커만 개발하여 외부 서비스와 연결할수 있다. 이런 경우에는 Borker만 Bosh release 로 설치 한다. 하지만 외부에서 제공하는 서비스가 CF 가 설치 되는 IaaS 에 포함(단절된 네트워크에서 cloud 운영인 경우)되는 경우에는 해당 service back-end 를 BOSH release로 배포한다. 또한 외부 서비스를 사용하고 Broker가 개방형 클라우드 플랫폼의 Application으로 (cf push) 제공 하려는 경우에는 BOSH release 는 생략 하고 2. Service Borker Guide 를 진행하면된다.

3.2. Bosh Architecture

  • 개방형 클라우드 플랫폼 아키텍쳐와 흡사함 (Message Bus, Health Monitor, Blobstore 등)
  • Director 는 Cloud Controller 와 유사한 기능
  • IaaS 종류에 따라 CPIs 구현 내용이 달라짐. (CPI : Cloud Provider Interface)
  • Worker 들은 Director에 의해 결정된 task 들을 실행시키는 역할을 함

3.3. Release Directory 구조

디랙토리 구조는 Bosh release 로 구성 할수 있게 되어 있다. Bosh는 릴리스 엔지니어링, 배포 및 대규모 분산 서비스의 라이프 사이클 관리를위한 오픈 소스 도구이다.

3.3.1. packages

packages에는 Boshrelease 설치를 위한 바이너리에 대한 종속성을 준비하는데 필요한 정보를 제공한다. (packaging, pre_packaging, spec 파일)

3.3.2. jobs

설치되는 package 들의 jobs(processes) 의 구동 및 정지 script 들과 모니터링(monit) script 로 구성한다.

3.3.3. src

service release 에서 사용하는 컨포넌트 소스 코드 또는 pre-compiled software 파일로 구성한다.

3.3.4. shared

ruby 및 lib 와 같은 공통 컴포넌트 소스를 관리한다. (옵션)

3.3.5. releases

  • 버전별 서비스 release yml 파일들을 관리한다.(yaml 설치 방식)
  • 버전별 서비스 release tgz 압축 파일들을 관리한다. (tarball 설치 방식)
  • Yaml 및 tarball 설치 방식은 아래 개발 가이드 참고한다.

3.3.6. config

최종 release를 저장하기 위한 Bosh blobstore에 URL 및 액세스 자격 증명을 위한 설정 파일로 구성한다.

3.3.7. final_builds

최종 jobs 및 packages 에 대한 public blobstore 정보를 제공한다.

3.3.8. deployments

IaaS 별 service 배포 manifest 파일 들을 관리한다.

3.3.9. content_migrations

이번버전으로 부터의 마이그레이션 정보 파일 들을 관리한다. (옵션)

3.4.개발 가이드

service를 Bosh release를 통해 배포 해야 하기 때문에 Bosh release 개발 방식에 따라 작성되어야한다.Bosh release 는 packages 와 jobs 관련 스크립트로 구성되어 있다. Bosh 는 software를 release 할 때 두가지 방식을 제공한다. Boshupload release CLI명령어 및 프로세스는 다음과 같다.
bosh upload release CLI boshupload release [] [--rebase] [--skip-if-exists] release_file: 로컬 파일 또는 원격 URI 정보 --rebase:최신 버전으로 Director에 설정 --skip-if-exists:릴리즈 가 존재 하면 업로드 하지 않음
  1. 1.
    Yaml 파일을 이용한 설치 프로세스 [ 파라미터가 yml 파일일 경우]: releases 디랙토리안에 cf--.yml 파일을 읽어서 sha1 값으로 .final_builds 폴더의 해당 packages 또는 jobs 폴더안의 index.yml 의 blobstore_id 로 config/final.yml 의 blobstore 에 접근하여 설치하는 방식이다.
  2. 2.
    tarball(설치할 release 파일을 모두 포함한 압축 파일: tgz 형식) 을 이용한 설치 프로세스 [ 파라미터가 tgz 파일일 경우]: blobstore 를 이용하지 않고 설치할 모든 packages 와 jobs 파일 및 release(release.MF), job메타 파일이 tgz 압축 파일 안에 있어서 blobstore에서 다운 받지 않고 설치하는 방식이다. (releases 디랙토리 안에 .tgz 파일로 압축)

3.4.1. packages 가이드

Service software 설치 관련하여 packaging, pre_packaging 와 spec 파일로 구성 되어 있다.
3.4.1.1. packaging
packaging 파일은 software 를 설치 하는 script 를 제공한다.
◎ packaging 파일 설명 1 “bosh generate package PACKAGE_NAME” 명령어로 packaging script file 를 자동생성한다. 1.1 예) $ bosh generate package test (service release 폴더에서 실행) 1.2 packages 폴더 안에 test package 폴더가 생성되고 해당 폴더에 packaging, pre_packaging, spec 파일 생성 1.3 bosh generate package 명령어로 하지 않고 수동으로 디랙토리 생성하여 파일을 만들어도 됨 2 컴파일시에 Bosh는 패키지 사양에 참조 된 소스 파일을 받아 배포 된 작업이 필요한 실행 가능한 바이너리 및 스크립트로 구성된다. 3 packaging scripts 작성시아래와 같은 내용을 포함한다. 3.1 Ruby 어플리케이션 경우 BOSH는 Ruby gems를 설치하고 소스파일을 복사해야 한다. (RubyGems은 루비 프로그램과 라이브러리를 배포하는 표준 형식을 제공하는 루비 프로그래밍 언어의 패키지 관리자) 3.2 Ruby 자체에 대해서는 BOSH는 binary 로 소스를 컴파일 해야 한다. 3.3 Python 어플리케이션 경우 BOSH는 Python eggs를 설치하고 소스파일을 복사해야 한다. 4 packaging script를 작성할 때 이러한 원칙을 준수한다. 4.1 “set -e –x” 으로 스크립트를 시작한다. 이는 에러가 발생하는 경우 즉시 종료 스크립트시킴으로써 컴파일시에 디버깅을 돕는다. 4.2 복사, 설치 또는 컴파일이 (BOSH_INSTALL_TARGET 환경 변수로 표현) 설치 대상 디렉토리에 코드가 생성 되는지 확인한다.“make” commands에 대한 use configure 또는 이에 상응하는 작업을 수행한다. 4.3 BOSH 패키지 사양 파일의 dependencies배포 된 바이너리를 사용할 수 있는지 확인해야 한다.
1
◎ Example libyaml packaging script
2
set -e -x
3
4
tar xzf libyaml_0.1.4/yaml-0.1.4.tar.gz
5
pushd yaml-0.1.4
6
./configure --prefix=${BOSH_INSTALL_TARGET}
7
8
make
9
make install
10
popd
11
12
◎ Example Ruby packaging script
13
set -e -x
14
15
tar xzf ruby_1.9.3/ruby-1.9.3-p484.tar.gz
16
pushd ruby-1.9.3-p484
17
./configure \
18
--prefix=${BOSH_INSTALL_TARGET} \
19
--disable-install-doc \
20
--with-opt-dir=/var/vcap/packages/libyaml_0.1.4
21
22
make
23
make install
24
popd
25
26
tar zxvf ruby_1.9.3/rubygems-1.8.24.tgz
27
pushd rubygems-1.8.24
28
${BOSH_INSTALL_TARGET}/bin/ruby setup.rb
29
popd
30
31
${BOSH_INSTALL_TARGET}/bin/gem install ruby_1.9.3/bundler-1.2.1.gem --no-ri --no-rdoc
32
33
◎ Example ruby_app packaging script
34
set -e -x
35
36
cp -a ruby_app/* ${BOSH_INSTALL_TARGET}
37
38
cd ${BOSH_INSTALL_TARGET}
39
40
/var/vcap/packages/ruby_1.9.3/bin/bundle install \
41
--local \
42
--deployment \
43
--without development test
Copied!
3.4.1.2. pre_packaging
pre_packaging 파일은 software 를 미리 packaging 하는 script 를 제공한다. (옵션) bosh document 에서는 pre_packaging 파일의 사용은 권장되지 않으며 이 튜토리얼에서 논의되지 않는다.(Use of the pre_packaging file is not recommended, and is not discussed in this tutorial.) https://bosh.io/docs/create-release.html#dev-release-release 문서에 명시되어 있음
1
◎ mysql-service-broker pre_packaging Sample
2
abort script on any command that exits with a non zero value
3
set -e
4
5
(
6
cd ${BUILD_DIR}/cf-mysql-broker
7
8
# cache gems
9
bundle package --all
10
11
RAILS_ENV=assets bundle exec rake assets:precompile
12
13
# remove unneeded files
14
rm -rf spec
15
)
Copied!
3.4.1.3. spec
설치할 package 의 메터 정보인 이름, dependencies 및 설치 파일 정보가 제공된다.
◎ spec 파일 설명 1 name: package 이름을 정의 2 dependencies: (옵션) 패키지에 의존하는 다른 패키지의 목록을 정의 3 files: 패키지에 포함 된 파일의 목록을 정의하거나 명시적 또는 패턴 매칭을 통해 파일 목록을 정의 할 수 있음 4 패키지 spec 파일을 편집 절차 4.1 모든 컴파일 시간 종속성을 확인한다. 패키지가 다른 패키지에 의존하는 경우 컴파일시 의존성이 발생한다. (4.2 spec 파일 생성후 dependeny 가 있을 경우에 dependencies 내용을 추가) 예) dependency 그래프
4.2 “bosh generate package PACKAGE_NAME” 명령어로 spec script file 를 자동생성한다. 4.2.1 예) $ bosh generate package test (service release 폴더에서 실행) 4.2.2 packages 폴더 안에 test package 폴더가 생성되고 해당 폴더에 packaging, pre_packaging, spec 파일 생성 4.2.3 bosh generate package 명령어로 하지 않고 수동으로 디랙토리 생성하여 파일을 만들어도 됨 4.3 package 가 필요로 하는 모든 파일들을 src 디렉토리에 복사한다. 일반적으로 파일은 소스 코드이다. 만일 pre-compiled software(예: ruby-1.9.3-p484.tar.gz)를 포함하는 경우, pre-compiled binary가 포함 된 압축 파일을 복사한다. 4.4 spec 파일 작성 4.4.1 해당 패키지이름(name) 과파일의 이름(files)을 추가 4.4.2 spec 파일에 어떤 compile-time dependencie의 이름을 추가. 패키지에는 compile-time dependencie가 없는 경우 빈 배열을 나타 내기 위해 []를 사용 4.4.3 files 부분은 먼저 src 디랙토리에서 해당 파일을 찾고 없을 경우 blobstore 의 blobs 에서 찾는다. 4.4.4 files 해당 파일이 소스로 구성되어 있을 경우에는 일반적으로 globbing pattern(/*/) 을 사용한다.
1
◎ Example Ruby package spec file
2
---
3
name: ruby_1.9.3
4
5
dependencies:
6
- libyaml_0.1.4
7
8
files:
9
- ruby_1.9.3/ruby-1.9.3-p484.tar.gz
10
- ruby_1.9.3/rubygems-1.8.24.tgz
11
- ruby_1.9.3/bundler-1.2.1.gem
Copied!

3.4.2. jobs 가이드

모든 job은 시작 및 중지하는 방법이 제공되어야 한다. 따라서 제어 스크립트를 작성하고 MONIT 파일을 작성하여해당 실행 되는 jobs(processes)를 모니터링 한다.
3.4.2.1. templates
설치된 package를 구동 및 정지 및 관련 설정 파일을 구성하는 템플릿 파일.
◎ control script 설명 : *.erb 화일 1 시작 명령과 중지 명령이 포함되어 있다. 2 관련 job에 대한 templates 디렉토리에 ERb template 형식으로 구성한다. (shell script로 구성) 3 각 job 에 대해 “/var/vcap/sys/log/JOB_NAME” 안에 로그 작업을 구성하는 제어 스크립트를 만든다.
1
◎ Example mariadb_ctl.erb
2
!/bin/bash -e
3
4
set -e
5
6
export MARIADB_JOB_DIR=/var/vcap/jobs/mysql
7
RUN_DIR=/var/vcap/sys/run/mysql
8
datadir=/var/vcap/store/mysql
9
LOG_DIR=/var/vcap/sys/log/mysql
10
LOG_FILE=$LOG_DIR/maria-ctl.log
11
CONFIG_DIR=/etc/mysql
12
export JOB_INDEX=<%= index %>
13
STATE_FILE=/var/vcap/store/mysql/state.txt
14
MYSQL_DAEMON_FILE=/var/vcap/packages/mariadb_ctrl/mysql_daemon.sh
15
MYSQL_CLIENT_FILE=/var/vcap/packages/mariadb/bin/mysql
16
MYSQL_SERVER_FILE=/var/vcap/packages/mariadb/support-files/mysql.server
17
DB_SEED_SCRIPT_FILE=$MARIADB_JOB_DIR/bin/mysql_database_seed.sh
18
package_dir=/var/vcap/packages/mariadb_ctrl
19
executable_name=mariadb_ctrl-executable
20
MYSQL_UPGRADE_SCRIPT_FILE=$package_dir/mysql_upgrade.sh
21
MYSQL_SHOW_DATABASES_SCRIPT_FILE=$package_dir/show_databases.sh
22
23
export MY_NAME=mariadb_ctl
24
export RUN_DIR=/var/vcap/sys/run/$MY_NAME
25
export PIDFILE=$RUN_DIR/$MY_NAME.pid
26
27
DATABASE_SEED_ATTEMPTS=30
28
29
source /var/vcap/packages/common/utils.sh
30
31
◎ add mysql to path
32
if [ ! -f /usr/local/bin/mysql ]; then
33
log "Adding mysql to path"
34
ln -s /var/vcap/packages/mariadb/bin/mysql /usr/local/bin
35
fi
36
37
◎ add xtrabackup to path
38
export PATH=$PATH:/var/vcap/packages/xtrabackup/bin
39
40
◎ add perl libraries to perl env
41
export PERL5LIB=$PERL5LIB:/var/vcap/packages/xtrabackup/lib/perl/5.18.2
42
43
case $1 in
44
45
◎ The start script must always exit 0 if there's a chance Maria could start successfully,
46
◎ as if monit sees a pid for Maria but this script exited with error, it will assume
47
◎ someone else started the process in the background.
48
◎ This will latch the status to "Execution failed" until someone manually calls
49
monit unmonitor && monit monitor, at which point monit would find the pid and reset the status to 'running'
50
51
start)
52
53
if [[ ! -d "$RUN_DIR" ]]; then
54
log "start script: directory $RUN_DIR does not exist, creating it now"
55
mkdir -p $RUN_DIR
56
fi
57
58
log "start script: checking for existing instance of $MY_NAME"
59
set +e
60
$(source /var/vcap/packages/common/utils.sh; pid_guard $PIDFILE $MY_NAME)
61
pg_exit_code=$?
62
log "start script: pg_exit_code: $pg_exit_code"
63
if [ $pg_exit_code -eq 1 ]; then
64
log "start script: $MY_NAME already running. Exiting 0 so that monit doesn't think that execution failed"
65
exit 0
66
fi
67
set -e
68
69
log "start script: writing pid $ for $MY_NAME to $PIDFILE"
70
echo $ > $PIDFILE
71
72
log "start script: checking if mysqld_safe is already running... "
73
set +e
74
pgrep -f /var/vcap/packages/mariadb/bin/mysqld_safe
75
result_code=$?
76
set -e
77
// Exit code of 0 means we did find a process, so we should exit.
78
if [ $result_code -eq 0 ]; then
79
log "start script: mysqld_safe already running - exiting with 0 so that monit doesn't think that execution failed"
80
exit 0
81
else
82
log "start script: mysqld_safe not already running - continue"
83
fi
84
85
Start syslog forwarding
86
/var/vcap/packages/syslog_aggregator/setup_syslog_forwarder.sh $MARIADB_JOB_DIR/config
87
88
mkdir -p $LOG_DIR
89
touch $LOG_FILE
90
chown vcap:vcap $LOG_FILE
91
date >> $LOG_FILE 2>> $LOG_FILE
92
93
It is surprisingly hard to get the config file location passed in
94
on the command line to the mysql.server script. This is easier.
95
mkdir -p $CONFIG_DIR
96
rm -f /etc/my.cnf
97
rm -f $CONFIG_DIR/my.cnf
98
ln -sf $MARIADB_JOB_DIR/config/my.cnf $CONFIG_DIR/my.cnf