在Openstack中实现节点高可用的方案中,探测物理节点宕机现象,在程序中调用了socket RAW 协议,但是必须具备root 用户权限,而openstack程序调用是nova用户,于是做了这样的事情,希望能帮助大家
1, 程序调用的错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<code>2014</code><code>-</code><code>03</code><code>-</code><code>1309</code><code>:</code><code>33</code><code>:</code><code>08.4081916TRACE</code> <code>nova.openstack.common.periodic_task Traceback (most recent call last):</code>
<code>2014</code><code>-</code><code>03</code><code>-</code><code>1309</code><code>:</code><code>33</code><code>:</code><code>08.4081916TRACE</code> <code>nova.openstack.common.periodic_task </code><code>File</code><code>"/usr/lib/python2.6/site-packages/nova/openstack/common/periodic_task.py"</code><code>, line </code><code>180</code><code>, inrun_periodic_tasks</code>
<code>2014</code><code>-</code><code>03</code><code>-</code><code>1309</code><code>:</code><code>33</code><code>:</code><code>08.4081916TRACE</code> <code>nova.openstack.common.periodic_task task(</code><code>self</code><code>, context)</code>
<code>2014</code><code>-</code><code>03</code><code>-</code><code>1309</code><code>:</code><code>33</code><code>:</code><code>08.4081916TRACE</code> <code>nova.openstack.common.periodic_task </code><code>File</code><code>"/usr/lib/python2.6/site-packages/nova/extend/manager.py"</code><code>, line </code><code>91</code><code>, inhealth_check_host</code>
<code>2014</code><code>-</code><code>03</code><code>-</code><code>1309</code><code>:</code><code>33</code><code>:</code><code>08.4081916TRACE</code> <code>nova.openstack.common.periodic_task ifnot icmp_ping.icmp_ping(node_resource[s][</code><code>'host_ip'</code><code>]) </code><code>and</code><code>\</code>
<code>2014</code><code>-</code><code>03</code><code>-</code><code>1309</code><code>:</code><code>33</code><code>:</code><code>08.4081916TRACE</code> <code>nova.openstack.common.periodic_task </code><code>File</code><code>"/usr/lib/python2.6/site-packages/nova/extend/icmp_ping.py"</code><code>, line </code><code>157</code><code>, inicmp_ping</code>
<code>2014</code><code>-</code><code>03</code><code>-</code><code>1309</code><code>:</code><code>33</code><code>:</code><code>08.4081916TRACE</code> <code>nova.openstack.common.periodic_task delay </code><code>=</code> <code>do_one(dest_addr, CONF.timeout)</code>
<code>2014</code><code>-</code><code>03</code><code>-</code><code>1309</code><code>:</code><code>33</code><code>:</code><code>08.4081916TRACE</code> <code>nova.openstack.common.periodic_task </code><code>File</code><code>"/usr/lib/python2.6/site-packages/nova/extend/icmp_ping.py"</code><code>, line </code><code>136</code><code>, indo_one</code>
<code>2014</code><code>-</code><code>03</code><code>-</code><code>1309</code><code>:</code><code>33</code><code>:</code><code>08.4081916TRACE</code> <code>nova.openstack.common.periodic_task ping_socket </code><code>=</code><code>socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)</code>
<code>2014</code><code>-</code><code>03</code><code>-</code><code>1309</code><code>:</code><code>33</code><code>:</code><code>08.4081916TRACE</code> <code>nova.openstack.common.periodic_task </code><code>File</code><code>"/usr/lib/python2.6/site-packages/eventlet/greenio.py"</code><code>, line </code><code>116</code><code>, in__init__</code>
<code>2014</code><code>-</code><code>03</code><code>-</code><code>1309</code><code>:</code><code>33</code><code>:</code><code>08.4081916TRACE</code> <code>nova.openstack.common.periodic_task fd </code><code>=</code><code>_original_socket(family_or_realsock, </code><code>*</code><code>args, </code><code>*</code><code>*</code><code>kwargs)</code>
<code>2014</code><code>-</code><code>03</code><code>-</code><code>1309</code><code>:</code><code>33</code><code>:</code><code>08.4081916TRACE</code> <code>nova.openstack.common.periodic_task </code><code>File</code><code>"/usr/lib64/python2.6/socket.py"</code><code>, line </code><code>184</code><code>, in__init__</code>
<code>2014</code><code>-</code><code>03</code><code>-</code><code>1309</code><code>:</code><code>33</code><code>:</code><code>08.4081916TRACE</code> <code>nova.openstack.common.periodic_task _sock </code><code>=</code><code>_realsocket(family, </code><code>type</code><code>, proto)</code>
<code>2014</code><code>-</code><code>03</code><code>-</code><code>1309</code><code>:</code><code>33</code><code>:</code><code>08.4081916TRACE</code> <code>nova.openstack.common.periodic_task error: [Errno </code><code>1</code><code>] Operation notpermitted</code>
2,icmp_ping 的实现,这是网上一个哥们写的ICMP 的实,下次找到贴上去,,我拿过来做了一些修改,希望作者不要见怪
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
<code># vim: tabstop=4 shiftwidth=4 softtabstop=4</code>
<code># Copyright 2010 United States Government as represented by the</code>
<code># Administrator of the National Aeronautics and Space Administration.</code>
<code># All Rights Reserved.</code>
<code># Copyright (c) 2010 Citrix Systems, Inc.</code>
<code># Copyright 2011 Ken Pepple</code>
<code>#</code>
<code># Licensed under the Apache License, Version 2.0 (the "License"); you may</code>
<code># not use this file except in compliance with the License. You may obtain</code>
<code># a copy of the License at</code>
<code># http://www.apache.org/licenses/LICENSE-2.0</code>
<code># Unless required by applicable law or agreed to in writing, software</code>
<code># distributed under the License is distributed on an "AS IS" BASIS, WITHOUT</code>
<code># WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the</code>
<code># License for the specific language governing permissions and limitations</code>
<code># under the License.</code>
<code>""" To detect physical nodes is active, according to the sock. Write the daemon ICMP protocol """</code>
<code>importos</code>
<code>importsys</code>
<code>#import socket</code>
<code>importstruct</code>
<code>importselect</code>
<code>importtime</code>
<code>importtraceback</code>
<code>fromoslo.config importcfg</code>
<code>fromnova.openstack.common importlog as logging</code>
<code>fromeventlet.green importsocket</code>
<code>icmp_opts </code><code>=</code><code>[</code>
<code> </code><code>cfg.StrOpt(</code><code>'timeout'</code><code>,</code>
<code> </code><code>default</code><code>=</code><code>3</code><code>,</code>
<code> </code><code>help</code><code>=</code><code>'Setting socket timeout'</code><code>),</code>
<code> </code><code>cfg.StrOpt(</code><code>'count'</code><code>,</code>
<code> </code><code>default</code><code>=</code><code>9</code><code>,</code>
<code> </code><code>help</code><code>=</code><code>'Setting the IMCP PING'</code><code>),</code>
<code>]</code>
<code>CONF </code><code>=</code><code>cfg.CONF</code>
<code>CONF.register_opts(icmp_opts)</code>
<code>LOG </code><code>=</code><code>logging.getLogger(__name__)</code>
<code># From /usr/include/linux/icmp.h; your milage may vary.</code>
<code>ICMP_ECHO_REQUEST </code><code>=</code><code>8</code><code># Seems to be the same on Solaris.</code>
<code>defchecksum(source_string):</code>
<code> </code><code>"""</code>
<code> </code><code>I'm not too confident that this is right but testing seems</code>
<code> </code><code>to suggest that it gives the same answers as in_cksum in ping.c</code>
<code> </code><code>sum</code><code>=</code><code>0</code>
<code> </code><code>countTo </code><code>=</code><code>(</code><code>len</code><code>(source_string)</code><code>/</code><code>2</code><code>)</code><code>*</code><code>2</code>
<code> </code><code>count </code><code>=</code><code>0</code>
<code> </code><code>whilecount<countTo:</code>
<code> </code><code>thisVal </code><code>=</code><code>ord</code><code>(source_string[count </code><code>+</code><code>1</code><code>])</code><code>*</code><code>256</code><code>+</code><code>ord</code><code>(source_string[count])</code>
<code> </code><code>sum</code><code>=</code><code>sum</code><code>+</code><code>thisVal</code>
<code> </code><code>sum</code><code>=</code><code>sum</code><code>& </code><code>0xffffffff</code><code># Necessary?</code>
<code> </code><code>count </code><code>=</code><code>count </code><code>+</code><code>2</code>
<code> </code><code>ifcountTo<</code><code>len</code><code>(source_string):</code>
<code> </code><code>sum</code><code>=</code><code>sum</code><code>+</code><code>ord</code><code>(source_string[</code><code>len</code><code>(source_string) </code><code>-</code><code>1</code><code>])</code>
<code> </code><code>sum</code><code>=</code><code>(</code><code>sum</code><code>>> </code><code>16</code><code>) </code><code>+</code> <code>(</code><code>sum</code><code>& </code><code>0xffff</code><code>)</code>
<code> </code><code>sum</code><code>=</code><code>sum</code><code>+</code><code>(</code><code>sum</code><code>>> </code><code>16</code><code>)</code>
<code> </code><code>answer </code><code>=</code><code>~</code><code>sum</code>
<code> </code><code>answer </code><code>=</code><code>answer & </code><code>0xffff</code>
<code> </code><code># Swap bytes. Bugger me if I know why.</code>
<code> </code><code>answer </code><code>=</code><code>answer >> </code><code>8</code><code>| (answer << </code><code>8</code><code>& </code><code>0xff00</code><code>)</code>
<code> </code><code>returnanswer</code>
<code>defreceive_one_ping(ping_socket, </code><code>ID</code><code>, timeout):</code>
<code> </code><code>receive the ping from the socket.</code>
<code> </code><code>timeLeft </code><code>=</code><code>timeout</code>
<code> </code><code>whileTrue:</code>
<code> </code><code>startedSelect </code><code>=</code><code>time.clock()</code>
<code> </code><code>whatReady </code><code>=</code><code>select.select([ping_socket], [], [], timeLeft)</code>
<code> </code><code>howLongInSelect </code><code>=</code><code>(time.clock() </code><code>-</code><code>startedSelect)</code>
<code> </code><code>ifwhatReady[</code><code>0</code><code>] </code><code>=</code><code>=</code><code>[]: </code><code># Timeout</code>
<code> </code><code>return</code>
<code> </code><code>timeReceived </code><code>=</code><code>time.clock()</code>
<code> </code><code>recPacket, addr </code><code>=</code><code>ping_socket.recvfrom(</code><code>1024</code><code>)</code>
<code> </code><code>icmpHeader </code><code>=</code><code>recPacket[</code><code>20</code><code>:</code><code>28</code><code>]</code>
<code> </code><code>type</code><code>, code, checksum, packetID, sequence </code><code>=</code><code>struct.unpack(</code>
<code> </code><code>"bbHHh"</code><code>, icmpHeader</code>
<code> </code><code>)</code>
<code> </code><code>ifpacketID </code><code>=</code><code>=</code><code>ID</code><code>:</code>
<code> </code><code>bytesInDouble </code><code>=</code><code>struct.calcsize(</code><code>"d"</code><code>)</code>
<code> </code><code>timeSent </code><code>=</code><code>struct.unpack(</code><code>"d"</code><code>, recPacket[</code><code>28</code><code>:</code><code>28</code><code>+</code><code>bytesInDouble])[</code><code>0</code><code>]</code>
<code> </code><code>returntimeReceived </code><code>-</code><code>timeSent</code>
<code> </code><code>timeLeft </code><code>=</code><code>timeLeft </code><code>-</code><code>howLongInSelect</code>
<code> </code><code>iftimeLeft <</code><code>=</code><code>0</code><code>:</code>
<code>defsend_one_ping(ping_socket, dest_addr, </code><code>ID</code><code>):</code>
<code> </code><code>Send one ping to the given >dest_addr<.</code>
<code> </code><code>dest_addr </code><code>=</code> <code>socket.gethostbyname(dest_addr)</code>
<code> </code><code># Header is type (8), code (8), checksum (16), id (16), sequence (16)</code>
<code> </code><code>my_checksum </code><code>=</code><code>0</code>
<code> </code><code># Make a dummy heder with a 0 checksum.</code>
<code> </code><code>header </code><code>=</code><code>struct.pack(</code><code>"bbHHh"</code><code>, ICMP_ECHO_REQUEST, </code><code>0</code><code>, my_checksum, </code><code>ID</code><code>, </code><code>1</code><code>)</code>
<code> </code><code>bytesInDouble </code><code>=</code><code>struct.calcsize(</code><code>"d"</code><code>)</code>
<code> </code><code>data </code><code>=</code><code>(</code><code>192</code><code>-</code><code>bytesInDouble) </code><code>*</code><code>"Q"</code>
<code> </code><code>data </code><code>=</code><code>struct.pack(</code><code>"d"</code><code>, time.clock()) </code><code>+</code><code>data</code>
<code> </code><code># Calculate the checksum on the data and the dummy header.</code>
<code> </code><code>my_checksum </code><code>=</code><code>checksum(header </code><code>+</code><code>data)</code>
<code> </code><code>header </code><code>=</code><code>struct.pack(</code>
<code> </code><code>"bbHHh"</code><code>, ICMP_ECHO_REQUEST, </code><code>0</code><code>, socket.htons(my_checksum), </code><code>ID</code><code>, </code><code>1</code>
<code> </code><code>)</code>
<code> </code><code>packet </code><code>=</code><code>header </code><code>+</code><code>data</code>
<code> </code><code>ping_socket.sendto(packet, (dest_addr, </code><code>1</code><code>)) </code><code># Don't know about the 1</code>
<code>defdo_one(dest_addr, timeout):</code>
<code> </code><code>Returns either the delay (in seconds) or none on timeout.</code>
<code> </code><code>icmp </code><code>=</code><code>socket.getprotobyname(</code><code>"icmp"</code><code>)</code>
<code> </code><code>try</code><code>:</code>
<code> </code><code>ping_socket </code><code>=</code><code>socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)</code>
<code> </code><code>#ping_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)</code>
<code> </code><code>exceptsocket.error, (errno, msg):</code>
<code> </code><code>iferrno </code><code>=</code><code>=</code><code>1</code><code>:</code>
<code> </code><code># Operation not permitted</code>
<code> </code><code>msg </code><code>=</code><code>msg </code><code>+</code><code>(</code>
<code> </code><code>" - Note that ICMP messages can only be sent from processes"</code>
<code> </code><code>" running as root."</code>
<code> </code><code>)</code>
<code> </code><code>LOG.error(socket.error(msg))</code>
<code> </code><code>raise</code><code># raise the original error</code>
<code> </code><code>my_ID </code><code>=</code><code>os.getpid() & </code><code>0xFFFF</code>
<code> </code><code>send_one_ping(ping_socket, dest_addr, my_ID)</code>
<code> </code><code>delay </code><code>=</code><code>receive_one_ping(ping_socket, my_ID, timeout)</code>
<code> </code><code>ping_socket.close()</code>
<code> </code><code>returndelay</code>
<code>deficmp_ping(dest_addr):</code>
<code> </code><code>active </code><code>=</code><code>False</code>
<code> </code><code>fori inxrange(CONF.count):</code>
<code> </code><code>try</code><code>:</code>
<code> </code><code>delay </code><code>=</code> <code>do_one(dest_addr, CONF.timeout)</code>
<code> </code><code>exceptsocket.gaierror, e:</code>
<code> </code><code>active </code><code>=</code><code>False</code>
<code> </code><code>break</code>
<code> </code><code>ifdelay </code><code>=</code><code>=</code> <code>None</code><code>:</code>
<code> </code><code>else</code><code>:</code>
<code> </code><code>active </code><code>=</code><code>True</code>
<code> </code><code>return</code> <code>active</code>
3,我单独写了一个openstack 的组件,来实现高可用(nova-extend),用他来调用 ICMP_PING
<code>"""Starter script for Nova Extend."""</code>
<code>fromnova importconfig</code>
<code>fromnova importobjects</code>
<code>fromnova importservice</code>
<code>fromnova importutils</code>
<code>CONF.import_opt(</code><code>'topic'</code><code>, </code><code>'nova.extend.api'</code><code>, group</code><code>=</code><code>'extend'</code><code>)</code>
<code>defmain():</code>
<code> </code><code>objects.register_all()</code>
<code> </code><code>config.parse_args(sys.argv)</code>
<code> </code><code>logging.setup(</code><code>"nova"</code><code>)</code>
<code> </code><code>utils.monkey_patch()</code>
4, nova-extend 启动服务的时候会调用nova.extend.manager.ExtendManager
<code>ifnot icmp_ping.icmp_ping(node_resource[s][</code><code>'host_ip'</code><code>]) </code><code>and</code><code>\</code>
<code> </code><code>utils.is_false(CONF.extend_high_availability):</code>
<code> </code><code>LOG.info(</code><code>"The compute node [%s] is down "</code><code>%</code><code>s)</code>
<code> </code><code>instances_uuid </code><code>=</code><code>db.instances_uuid_by_host(context,s)</code>
5, 程序就会报错,
<code>2</code>
6 ,我用python 调用是OK 的,但是openstack调用依然报错,我以为是协程限制导致,岂不是,我是这样处理的
1, copy /usr/bin/python /usr/bin/python-extend
2, chown root:root /usr/bin/python-extend
3, chmod ug+s /usr/bin/python-extend
4, 修改/usr/bin/nova-extend
#!/usr/bin/python-extend
5,重启服务就OK 了
本文转自 swq499809608 51CTO博客,原文链接:http://blog.51cto.com/swq499809608/1375260