Sunday, December 25, 2016

回顧2016

2016review

2016回顧

2016是一個很不容易的一年。 奔波在台灣與大陸間,有的時候,還覺得在大陸工作愉快些。
在這一年,學會了競爭與感激。 1. 競爭:
大陸團隊的擴張,我想做的只有一件事,當他們帶著挑戰的心情與我討論,我要讓他們笑的離開,並還會再找我討論。
2. 感激:
這一切都不容易,我感激我周遭的人,縱使他們因為無知而傷害著彼此,我感激他們。

多麼心機的一年,不舒服的一年,但也在此環境下成長,每一步,得學會忍耐與分析現狀,並突破自己。

在2016年開始時,我寫下了這一段話:

柔順謙遜,精中求細,剛健文明,應乎天時。

回頭看,這句話是完全正確的,我努力的奉行著,但卻不夠好。
很可惜,都知道答案了,卻無法100%的展現執行力,真的可惜。
各總情況的發生考驗著處理情緒的能力,忍靜著將一切轉成謀略。
我深知,必須忍耐著,不能忍,將無法執行任何謀略。
每一個狀況,我都在壓力下確認著,我到底要什麼,因此我該做什麼與不該做什麼。
每一個狀況,我都反覆思量著,我應該要用什麼態度,才能正確反應出我該有的反應。
聽起來就是很難受吧,是的,的確如此。
在我工作的周遭,不是朋友也沒有敵人,而這讓一切更不容易了。

常常,我把自己比喻成司馬懿,我還真他媽的處境有點類似。
在這樣的處境下生存著,那種懷疑與不信任對抗著,司馬懿不放棄,用了各種方法,而我也能撐過去。
撐,是一個很棒的字眼,有的時候撐過去,事情就會完全不同了。
這個司馬懿的比喻,讓我撐著渡過每個不愉悅,甘心忍耐與等待,並讓每個謀略實現。
在那時,我寫下這段話:

享受競爭。
享受人與人之間的懷疑不信任。
享受內與外的不協調。
享受忍耐與低調。
享受恐懼與不確定。
我已經不能停下腳步了。
因為那種不舒服的感覺只是感覺罷了。
沒什麼了不起。
因為世界很大.所以沒什麼好怕的。
要突破就享受這一切吧。
但,其實反著說,
臉皮厚,心要黑,才能享受這ㄧ切。

很悲傷,真的,我是如此悲傷的寫下這段話。
這違反著我這幾年工作的方法,態度,經驗,我不喜歡。
但我得這麼去做,這麼去想,唯有這樣,事情會更順利些。 因為,我了解,最重要的是,事情能夠做好。
透過這樣的修正,慢慢的我也懂得如何思考,如何放置那些讓人不愉悅的人,並讓自己得利,讓事情順利:

有一個正面的模仿對象,可以讓你方向正確,同時有一個負面的討厭對象,可以讓你更積極的邁開步伐走向正確方向。

所有的目的,是讓事情完成,而事情是人做的,但人很複雜。
必須用以大事小的態度對待你的周圍。
運行正確的態度,包含: 不亂抱怨,沒有過多的情緒,學習讓爭論互有勝負。

  1. 不亂抱怨:
    在一個會議裡,如果只是抱怨著講師的內容, 這,不代表你比他懂,反而,最終,你毫無所得。 這個現象,屢試不爽。有時候,我們得想想,為何而來.....。 是要學點東西回去,還是來此否定一切。

    贏家專注在自己的跑道,酸民看著別人的跑道。

  2. 沒有過多的情緒:
    過去,曾經有個同事,完全無法控制自己的情緒(我們都犯過這樣的錯)。 在辦公室中多次咆嘯,我看懂了這種醜陋與噁心,因此努力的阻止自己變成這樣的人。
    當發現用情緒做事的人是如此可悲與幼稚,誰也不願意成為那樣的人吧。

    用謀略完成事情,而不是情緒,情緒只會將事情搞砸。要控制情緒,先閉起你的嘴吧。

  3. 在同一個團體中,讓爭論互有勝負
    爭論,是一件複雜的事情,你想贏是吧! 如果只是爭著贏,而不讓別人在這過程中,也獲得一些小勝利,這不是贏。
    讓別人贏一些,只要當最大的贏家即可,不用全贏。
    多讚美人,讓人感覺自己是中立的,讓步,是因為展現中立,得到別人的信賴。
    因此,最後,你的堅持,會讓別人更認同你。所以,在不重要的地方讓步,在重要的地方堅持。

    總是在立場上爭到頭破血流是件蠢事,笑到最後的才是贏家,看著自己的謀略一步一步被實踐才叫成功。

在2016,一切都不容易,內憂外患,要克服這些,只能不斷的修煉自己。
但縱使如此,我感激這些人,事,物。

反思這一年,自己依舊不夠勤勞,沒有投入100%的時間,讓事情更偉大。

Think Big, Doing Big, Win Big.

所以,用馬雲的一句話送給2017年的自己吧

感激過去,珍惜現在,敬畏明天

Tuesday, November 8, 2016

Influxdb Installation and Playing

influxdb

InfluxDB Testing

Installation

Get influxdb apt repository

wget -O- https://repos.influxdata.com/influxdb.key | apt-key add -
root@influxdb:~# apt-key list
/etc/apt/trusted.gpg
--------------------
.
.

pub   4096R/2582E0C5 2015-09-28
uid                  InfluxDB Packaging Service <support@influxdb.com>
sub   4096R/87F70D56 2015-09-28
root@influxdb:~# source /etc/lsb-release
root@influxdb:~# echo "deb https://repos.influxdata.com/${DISTRIB_ID,,} ${DISTRIB_CODENAME} stable" | tee /etc/apt/sources.list.d/influxdb.list

Update Repository and install influxdb

root@influxdb1:~#apt-get update
root@influxdb1:~# apt-get -y install influxdb
.
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  influxdb
0 upgraded, 1 newly installed, 0 to remove and 174 not upgraded.
Need to get 17.8 MB of archives.
After this operation, 64.0 MB of additional disk space will be used.
Fetched 17.8 MB in 57s (308 kB/s)
Selecting previously unselected package influxdb.
(Reading database ... 49929 files and directories currently installed.)
Preparing to unpack .../influxdb_1.0.2-1_amd64.deb ...
Unpacking influxdb (1.0.2-1) ...
Processing triggers for man-db (2.6.7.1-1ubuntu1) ...
Setting up influxdb (1.0.2-1) ...
 Adding system startup for /etc/init.d/influxdb ...
   /etc/rc0.d/K20influxdb -> ../init.d/influxdb
   /etc/rc1.d/K20influxdb -> ../init.d/influxdb
   /etc/rc6.d/K20influxdb -> ../init.d/influxdb
   /etc/rc2.d/S20influxdb -> ../init.d/influxdb
   /etc/rc3.d/S20influxdb -> ../init.d/influxdb
   /etc/rc4.d/S20influxdb -> ../init.d/influxdb
   /etc/rc5.d/S20influxdb -> ../init.d/influxdb

Start playing

Use 8086 port.

Create DB first

root@influxdb1:~# curl -X POST http://localhost:8086/query --data-urlencode "q=CREATE DATABASE mydb"
{"results":[{}]}

Write data

root@influxdb1:~# curl -i -XPOST 'http://localhost:8086/write?db=mydb' --data-binary 'cpu_load_short,host=server02 value=0.67'
HTTP/1.1 204 No Content
Content-Type: application/json
Request-Id: bef013e7-a593-11e6-8004-000000000000
X-Influxdb-Version: 1.0.2
Date: Tue, 08 Nov 2016 09:14:26 GMT

Query data

root@influxdb1:~# curl -i 'http://localhost:8086/query?db=mydb' --data-urlencode "q=SELECT value FROM cpu_load_short"
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Request-Id: 0707f706-a594-11e6-8007-000000000000
X-Influxdb-Version: 1.0.2
Date: Tue, 08 Nov 2016 09:16:27 GMT
Transfer-Encoding: chunked

{"results":[{"series":[{"name":"cpu_load_short","columns":["time","value"],"values":[["2016-11-08T09:14:26.355967704Z",0.67]]}]}]}

Monday, November 7, 2016

Numa Setting

numa

Numa Setting

What is a Numa

Simplly said, Numa has a share memory charachtoristic.
Numa node means share the same pool of memory.
So if a process running in same Numa node, it will get better performance.
Let's see it.

Check Server Numa Node

To get Numa node

[root@openstackha11 ~]# cat /sys/devices/system/node/
has_cpu            node0/             possible
has_memory         node1/             power/
has_normal_memory  online             uevent

To get Numa node's CPU

[root@openstackha11 ~]# cat /sys/devices/system/node/node0/cpulist
0-5,12-17
[root@openstackha11 ~]# cat /sys/devices/system/node/node1/cpulist
6-11,18-23

Set Numa for a Process

Set up a Process to a CPU range(Numa Node)

[root@openstackha11 ~]# taskset -cp 6-11,18-23 24122
pid 24122's current affinity list: 0-23
pid 24122's new affinity list: 6-11,18-23
You have new mail in /var/spool/mail/root

where 6-11,18-23 obtained by numa node.

Tuesday, November 1, 2016

公司食物鏈

公司的食物鏈,依序是
搞關係,搞錢,搞人,搞很多很多事,搞很多事,只搞一件事。

你是哪一項?而你的目標又在哪?


Monday, October 31, 2016

停止生氣與憤怒

幾十個年頭下來,至少體悟到,
在憤怒時說的話,後悔的都是自己。
不管你多有理由,不管你多冠冕堂皇,後悔的都是自己。

生氣其實是脆弱引發的,接著失控,因此導致自己的後悔。
如果把憤怒,轉變成思路與策略,我想一切都會很不同。

從另一個角度看:
這也暴露了人類的弱點,憤怒是最脆弱的時刻,
打倒你,很簡單,惹怒你就好,永比射向阿基里斯腱容易。

或許,你不會藉機惹怒別人,但別人會。
別上當了,因此,請學會控制自己,

如果這樣寫的都無法打動自己,
那麼,請相信猶太人相信的,和氣生財。

Tuesday, October 4, 2016

OpenStack: How to bind a Tenant/Project to a Specific Region

keystonetenantbindRegion

How to bind a Tenant to a specific Region

Long time ago, I am trying to solve the problem that can a tenant bind to a region ?
Now we got the answer, we can use Mitaka keystone and with v3 API to solve this problem.

http://developer.openstack.org/api-ref/identity/v3-ext/?expanded=create-endpoint-group-detail

V3 API changes the Tenant to Project, so sometimes we use these two words mix.

We can use the keystone v3 extension API: v3/OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id}.

Started Binding Tenant and Region

先找出来,我们现有的Region ID。 First of all, we find out the region that we want to bind to.

root@mitakakeystone:~/v3keystone# curl  -si -H"X-Auth-Token:admintoken" -H "Content-type: application/json" "http://localhost:35357/v3/endpoints"
HTTP/1.1 200 OK
Vary: X-Auth-Token
Content-Type: application/json
Content-Length: 3327
X-Openstack-Request-Id: req-99c406c8-2f1e-41b8-8bb4-bfad7beb2c99
Date: Tue, 04 Oct 2016 06:20:45 GMT

.
 {"region_id": "RR", "links": {"self": "http://localhost:35357/v3/endpoints/909a15358430456cab93020fab101b9f"},   
 "url": "http://localhost:35357/v3/services/c6f427a715a54d0190ec8364d46f307b", "region": "RR", "enabled": true,   
 "interface": "public", "service_id": "c6f427a715a54d0190ec8364d46f307b", "id": "909a15358430456cab93020fab101b9f"}   
.

Remember the Region_ID 909a15358430456cab93020fab101b9f, we will bind a project to this region.

That's see Is there any endpoint binding to the project(tenant) id via /v3/OS-EP-FILTE API.

root@mitakakeystone:~/v3keystone# curl -si -H "X-Auth-Token:admintoken" -H "Content-type: application/json" "http://localhost:35357/v3/OS-EP-FILTER/projects/404838490fab42e7ad560b66725e4f64/endpoints"
HTTP/1.1 200 OK
Vary: X-Auth-Token
Content-Type: application/json
Content-Length: 162
X-Openstack-Request-Id: req-560e8715-e992-42e6-b761-9c3487040a93
Date: Tue, 04 Oct 2016 06:16:38 GMT

{"endpoints": [], "links": {"self": "http://localhost:35357/v3/OS-EP-FILTER/projects/404838490fab42e7ad560b66725e4f64/endpoints", "previous": null, "next": null}}

No binding at all.

Now we can start to bind project id 404838490fab42e7ad560b66725e4f64 to Region ID 909a15358430456cab93020fab101b9f

curl -X PUT -si -H "X-Auth-Token:admintoken" -H "Content-type: application/json" "http://localhost:35357/v3/OS-EP-FILTER/projects/404838490fab42e7ad560b66725e4f64/endpoints/909a15358430456cab93020fab101b9f"

To check it out.

root@mitakakeystone:~/v3keystone# curl -si -H "X-Auth-Token:admintoken" -H "Content-type: application/json" "http://localhost:35357/v3/OS-EP-FILTER/projects/404838490fab42e7ad560b66725e4f64/endpoints"
HTTP/1.1 200 OK
Vary: X-Auth-Token
Content-Type: application/json
Content-Length: 498
X-Openstack-Request-Id: req-404dd3f3-df71-4665-bd8e-acae1f33b2a9
Date: Tue, 04 Oct 2016 06:18:02 GMT

{"endpoints": [{"region_id": "RR", "links": {"self": "http://localhost:35357/v3/endpoints/909a15358430456cab93020fab101b9f"}, "url": "http://localhost:35357/v3/services/c6f427a715a54d0190ec8364d46f307b", "region": "RR", "enabled": true, "interface": "public", "service_id": "c6f427a715a54d0190ec8364d46f307b", "id": "909a15358430456cab93020fab101b9f"}], "links": {"self": "http://localhost:35357/v3/OS-EP-FILTER/projects/404838490fab42e7ad560b66725e4f64/endpoints", "previous": null, "next": null}}

We can see we can bind the project to a spcific region.

To see the original API, no changes any more

root@mitakakeystone:~/v3keystone# curl  -si -H"X-Auth-Token:admintoken" -H "Content-type: application/json" "http://localhost:35357/v3/projects/404838490fab42e7ad560b66725e4f64"
HTTP/1.1 200 OK
Vary: X-Auth-Token
Content-Type: application/json
Content-Length: 283
X-Openstack-Request-Id: req-26d3a544-83ac-4b9b-a10b-ba7f5bbfbf19
Date: Tue, 04 Oct 2016 06:29:47 GMT

{"project": {"is_domain": false, "description": "Service Tenant", "links": {"self": "http://localhost:35357/v3/projects/404838490fab42e7ad560b66725e4f64"}, "enabled": true, "id": "404838490fab42e7ad560b66725e4f64", "parent_id": "default", "domain_id": "default", "name": "service1"}}

So to solve the problem, we must use v3/OS-EP-FILTER/ API.

Thursday, September 22, 2016

Explaining Keystone Domain, Project, Group, User and Role in a Single Image

keystoneUserandRole

Explaining Keystone Domain, Project, Group, User and Role in a Single Image

  1. Fig1
    • Each Domain is unique in OpenStack
    • Different Project can be mapped to one Domain, but cannot map to another Domain
  2. Fig2
    • One User can be mapped to different Prject
    • One User have different role in different Project
  3. Fig 3
    • Different User can map to one Group
    • One Group can be mapped to different Project
    • One Group can have different role to different Project
  4. Fig 4
    • Domains have admin
    • Projects have admin
    • Group have admin
    • Group can have different admin to different Project

Playing Haproxy in Layer 7 : Redirect Traffics to Different Backends Based on HTTP Reqeust Header

haproxy

Playing Haproxy in Layer 7 : Redirect Traffics to Different Backends Based on HTTP Reqeust Header

Haproxy 1.6 installation

Following the steps to install haproxy 1.6.

sudo add-apt-repository ppa:vbernat/haproxy-1.6
sudo apt-get update
sudo apt-get dist-upgrade
apt-get install haproxy

Simple testing

Simply test the haproxy we installed to make sure the haproxy is right.

adding to /etc/haproxy/haproxy.cfg

global
  log         127.0.0.1 syslog
  maxconn     1000
  user        haproxy
  group       haproxy
  daemon

defaults
  log  global
  mode  http
  option  httplog
  option  dontlognull
  option  http-server-close
  option  forwardfor except 127.0.0.0/8
  option  redispatch
  option  contstats
  retries  3
  timeout  http-request 10s
  timeout  queue 1m
  timeout  connect 10s
  timeout  client 1m
  timeout  server 1m
  timeout  check 10s

listen  http_proxy
  bind        127.0.0.1:80
  balance     roundrobin
  server      server1 127.0.0.1:6000 maxconn 100

Runing the python SimpleHTTPServer as a Haproxy Backend Server.

root@haproxy:~# python -m SimpleHTTPServer 6000
Serving HTTP on 0.0.0.0 port 6000 ...

Using Curl to test it. You should get the following result and the result is right. Now we can go to next step.

root@haproxy:~# curl 127.0.0.1:80
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
<title>Directory listing for /</title>
<body>
<h2>Directory listing for /</h2>
<hr>
<ul>
<li><a href=".bash_history">.bash_history</a>
<li><a href=".bashrc">.bashrc</a>
<li><a href=".cache/">.cache/</a>
<li><a href=".profile">.profile</a>
<li><a href=".ssh/">.ssh/</a>
<li><a href=".viminfo">.viminfo</a>
<li><a href="haproxy.cfg">haproxy.cfg</a>
<li><a href="sources.list">sources.list</a>
</ul>
<hr>
</body>

Redirect by Layer 7 header

Now we are going to redirect traffic according to reqeust header information.

Simple Cases to capture header

An simple test to make sure the haproxy knowing the request header.

Chaning the /etc/haproxy/haproxy.cfg

global
 # variables memory consumption, in bytes
 tune.vars.global-max-size 1048576
 tune.vars.reqres-max-size     512
 tune.vars.sess-max-size      2048
 tune.vars.txn-max-size        256
 log         127.0.0.1 syslog
  maxconn     1000
  user        haproxy
  group       haproxy
  daemon

defaults
 mode http

frontend f_myapp
 bind 127.0.0.1:80
 http-request set-var(txn.host) req.hdr(Host)
 http-request set-var(txn.ua) req.hdr(User-Agent)
 default_backend b_myapp

backend b_myapp
 http-response set-header Your-Host %[var(txn.host)]
 http-response set-header Your-User-Agent %[var(txn.ua)]
 server s1 127.0.0.1:6000 check

Test it. And you will see the response informaiton contains the request header information (host, and User-Agent).

curl -H "host":"hhh" -H "User-Agent":"hhh" http://127.0.0.1:80 -sv
.
.
> Accept: */*
> host:hhh
> User-Agent:hhh
.
.

Try this and you will NOT see the response header contains the reqest header.

curl http://127.0.0.1:80 -sv

Redirect the traffic by Header

This topic is the most important.
According to the following config setting, we can redirect the traffic to different backends based on the request header.

/etc/haproxy/haproxy.cfg

global
 # variables memory consumption, in bytes
 tune.vars.global-max-size 1048576
 tune.vars.reqres-max-size     512
 tune.vars.sess-max-size      2048
 tune.vars.txn-max-size        256
 log         127.0.0.1 syslog
  maxconn     1000
  user        haproxy
  group       haproxy
  daemon

defaults
 mode http

frontend f_myapp
 bind 127.0.0.1:80

use_backend bk_app1 if { hdr(Host) -i app1.domain1.com app1.domain2.com region2 }
 default_backend b_myapp

backend bk_app1
 http-response set-header Your-Host %[var(txn.host)]
 http-response set-header Your-User-Agent %[var(txn.ua)]
 server s1 127.0.0.1:7000 check

backend b_myapp
 http-response set-header Your-Host %[var(txn.host)]
 http-response set-header Your-User-Agent %[var(txn.ua)]
 server s1 127.0.0.1:6000 check
root@haproxy:~# python -m SimpleHTTPServer 7000
Serving HTTP on 0.0.0.0 port 7000 ...

When hdr(Host) satisfies the condition of app1.domain1.com app1.domain2.com region2, the traffic will be redirect to bk_app1 that is the port 7000 running by SimpleHTTPServer.
When hdr(Host) NOT satisfies the condition, it will be redirect to default_backend b_myapp.
For simply, we shutdown the port 6000 backend server.

You can test app1.domain1.com, app1.domain2.com, and region2 as the reqeust header.

root@haproxy:~# curl -H "Host:"region2" " http://127.0.0.1:80 -sv
* Rebuilt URL to: http://127.0.0.1:80/
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Accept: */*
> Host:region2
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
.
.

Try region3 and it should return 503 since we didn't launch port 6000 for detection the error.

root@haproxy:~# curl -H "Host:"region3" " http://127.0.0.1:80 -sv
* Rebuilt URL to: http://127.0.0.1:80/
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Accept: */*
> Host:region3
>
* HTTP 1.0, assume close after body
< HTTP/1.0 503 Service Unavailable
< Cache-Control: no-cache
< Connection: close
< Content-Type: text/html
<
<html><body><h1>503 Service Unavailable</h1>
No server is available to handle this request.
</body></html>
* Closing connection 0

Some Warning

When we restart the haproxy, we found some warning as followed.
But it not affect our experience, so we ignore it.

root@haproxy:~# service haproxy restart
 * Restarting haproxy haproxy                                                                                                                                                        [WARNING] 265/160929 (3164) : config : missing timeouts for frontend 'f_myapp'.
   | While not properly invalid, you will certainly encounter various problems
   | with such a configuration. To fix this, please ensure that all following
   | timeouts are set to a non-zero value: 'client', 'connect', 'server'.
[WARNING] 265/160929 (3164) : config : missing timeouts for backend 'bk_app1'.
   | While not properly invalid, you will certainly encounter various problems
   | with such a configuration. To fix this, please ensure that all following
   | timeouts are set to a non-zero value: 'client', 'connect', 'server'.
[WARNING] 265/160929 (3164) : config : missing timeouts for backend 'b_myapp'.
   | While not properly invalid, you will certainly encounter various problems
   | with such a configuration. To fix this, please ensure that all following
   | timeouts are set to a non-zero value: 'client', 'connect', 'server'.
[WARNING] 265/160929 (3165) : config : missing timeouts for frontend 'f_myapp'.
   | While not properly invalid, you will certainly encounter various problems
   | with such a configuration. To fix this, please ensure that all following
   | timeouts are set to a non-zero value: 'client', 'connect', 'server'.
[WARNING] 265/160929 (3165) : config : missing timeouts for backend 'bk_app1'.
   | While not properly invalid, you will certainly encounter various problems
   | with such a configuration. To fix this, please ensure that all following
   | timeouts are set to a non-zero value: 'client', 'connect', 'server'.
[WARNING] 265/160929 (3165) : config : missing timeouts for backend 'b_myapp'.
   | While not properly invalid, you will certainly encounter various problems
   | with such a configuration. To fix this, please ensure that all following
   | timeouts are set to a non-zero value: 'client', 'connect', 'server'.

Friday, September 9, 2016

Minimun Installation Steps to Ceph Jewel and Plaing with It

Cephjewelinstall

Minimun Installation Steps to Ceph Jewel and Plaing with It

Our goal is to reduce the installation procudures that can help peolple playing Ceph Jewel immediately.
Hence, we use the minimum installation with single VM and one disk drive to achive the goal.
I do not recommand using OS direcotry as OSD drive, since it's not a usual situation.
So attaching one disk on this VM first.

Let's start to discuss the following topic.

  • Envrironment
  • Installation
  • Result
  • Playing with Ceph Jewel

Envrironment

OS

  • Ubuntu14.04
  • Kernel 3.16.0-30-generic
  • VMware VM

/etc/hosts Setting

root@cephserver:~/mycephfiles# cat /etc/hosts
127.0.0.1   localhost

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.2.141 cephserver

Data Drive setting

root@cephserver:~/mycephfiles# ls /dev/sd*
sda   sda1  sda2  sda5  sdb

The sdb will be the only one OSD in our Ceph testing bed

Ceph Jewel Installation

We installed the Ceph Jewel by using the following commands.

wget -q -O- 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc' | sudo apt-key add -
echo deb http://download.ceph.com/debian-jewel/ $(lsb_release -sc) main | sudo tee /etc/apt/sources.list.d/ceph.list
sudo apt update
apt-get install ceph-deploy
mkdir mycephfiles
cd mycephfiles
ceph-deploy new cephserver
echo 'osd crush chooseleaf type = 0' >> ceph.conf
echo osd pool default size = 1 >> ceph.conf
ceph-deploy install cephserver
ceph-deploy mon create-initial
mkfs.ext4 /dev/sdb
ceph-deploy osd create cephserver:sdb
ceph-deploy osd activate cephserver:/dev/sdb1
ceph-deploy admin cephserver
chmod +r /etc/ceph/ceph.client.admin.keyring
Ceph -s
ceph osd tree

Result

After installation, we check the Ceph is healthy or not. First of all, check the status of Ceph.

root@cephserver:~# ceph -s
    cluster af0ac66e-5020-4218-926a-66d57895fafd
     health HEALTH_WARN
            too many PGs per OSD (448 > max 300)
     monmap e1: 1 mons at {cephserver=192.168.2.141:6789/0}
            election epoch 5, quorum 0 cephserver
     osdmap e24: 1 osds: 1 up, 1 in
            flags sortbitwise
      pgmap v230: 448 pgs, 4 pools, 3291 MB data, 947 objects
            3333 MB used, 1990 GB / 1994 GB avail
                 448 active+clean

Check the status of all the OSD, it must be the "up" status.

root@cephserver:~# ceph osd tree
ID WEIGHT  TYPE NAME           UP/DOWN REWEIGHT PRIMARY-AFFINITY
-1 1.94730 root default
-2 1.94730     host cephserver
 0 1.94730         osd.0            up  1.00000          1.00000

As before, we directly activate the /dev/sdb, and now we can see which directory it located.

root@cephserver:~# mount 
.
.
/dev/sdb1 on /var/lib/ceph/osd/ceph-0 type xfs (rw,noatime,inode64)

Playing with Ceph Jewel

A big Difference to Other Ceph version

Ceph Jewel is running properly in Kernel greater than 4.4. So, if you kernel is less the 4.4, you will get the errors when you map a image shown as followed.

root@cephserver:~#rbd map pool101/realimage1

rbd: sysfs write failed
RBD image feature set mismatch. You can disable features unsupported by the kernel with "rbd feature disable".
In some cases useful info is found in syslog - try "dmesg | tail" or so.
rbd: map failed: (6) No such device or address

The solution is disable some features to make it working properly by using the below command.

rbd feature disable pool101/realimage1 deep-flatten fast-diff object-map exclusive-lock
rbd map pool101/realimage1

Playing Pool, Create, Map and Mount

Now we can add some data in the Ceph.

root@cephserver:~# ceph osd pool create pool101 128
root@cephserver:~# rbd create -p pool101 realimage1 --size 102400 --image-format 2
rbd feature disable pool101/realimage1 deep-flatten fast-diff object-map exclusive-lock
root@cephserver:~# rbd map pool101/realimage1
/dev/rbd0
root@cephserver:~# mkfs.ext4 /dev/rbd0
root@cephserver:~# mount /dev/rbd0 /mnt/cephtest/
root@cephserver:~# touch /mnt/cephtest/aa && echo "v1"> /mnt/cephtest/aa

Playing Snapshot

You can snapshot the data, and the snapshot is read only.

root@cephserver:~# rbd snap create pool101/realimage1@snap1
rbd snap protect pool101/realimage1@snap1

Playing Clone and Mount

If you want to write to some snapshot, you have to clone the snapshot. Now you can read and write the data to it.

root@cephserver:~# rbd clone pool101/realimage1@snap1 realimage1snap1clone1
root@cephserver:~#rbd feature disable realimage1snap1clone1 deep-flatten fast-diff object-map exclusive-lock
root@cephserver:~# rbd map realimage1snap1clone1
/dev/rbd1
root@cephserver:~# mount /dev/rbd1 /mnt/cephclone
root@cephserver:~# cat /mnt/cephclone/aa
v1

Tuesday, August 30, 2016

Trace Source Code: nova scheduler (OpenStack Kilo)

scheduler

Code tracing in Nova Scheduler (Kilo)

Nova Scheduler in Kilo

We started from nova/nova/scheduler/manage.py and its function select_destinations,
that is the beginning of the nova-schduler.
Here is the an example for quick understanding the RabbitMQ Server Side that compared the section of reference for oslo.messaging in this Blog.

And the Client side is from nova-conductor.

And the nova/nova/scheduler/manage.py is here.

class SchedulerManager(manager.Manager):
    """Chooses a host to run instances on."""

    target = messaging.Target(version='4.2')

    def __init__(self, scheduler_driver=None, *args, **kwargs):
        if not scheduler_driver:
            scheduler_driver = CONF.scheduler_driver
        self.driver = importutils.import_object(scheduler_driver)
        super(SchedulerManager, self).__init__(service_name='scheduler',
                                               *args, **kwargs)
        self.additional_endpoints.append(_SchedulerManagerV3Proxy(self))
        
    @messaging.expected_exceptions(exception.NoValidHost)
    def select_destinations(self, context, request_spec, filter_properties):

This is the result of tracing nova scheduler code.

Adding more filter, you can put it on /schedule/filters and reconfig nova.conf to add the new filter you put.

Reference for oslo.messaging

http://www.cinlk.com/2015/12/04/rabbitmq/

import oslo.messaging
from oslo.config import cfg
class TestEndpoint(object):
    target = oslo.messaging.Target(namespace='test', version='2.0')
    def __init__(self, server):
        self.server = server
    def foo(self, ctx, id):
        return id
oslo.messaging.set_transport_defaults('myexchange')
transport = oslo.messaging.get_transport(cfg.CONF)
target = oslo.messaging.Target(topic='myroutingkey', server='myserver')
endpoints = [TestEndpoint(None)]
server = oslo.messaging.get_rpc_server(transport, target, endpoints,
                                      executor='blocking')
server.start()
server.wait()