Skip to content

Commit 01dada1

Browse files
author
Frank Zhang
committed
CLOUDSTACK-6278
Baremetal Advanced Networking support
1 parent aed36c2 commit 01dada1

6 files changed

Lines changed: 148 additions & 4 deletions

File tree

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
build/replace.properties
1919
build/build.number
20-
bin/
2120
.lock-wscript
2221
.waf-*
2322
waf-*

plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ private boolean preparePxeInAdvancedZone(VirtualMachineProfile profile, NicProfi
230230
}
231231

232232
List<String> tuple = parseKickstartUrl(profile);
233-
String cmd = String.format("/usr/bin/prepare_pxe.sh %s %s %s %s %s %s", tuple.get(1), tuple.get(2), profile.getTemplate().getUuid(),
233+
String cmd = String.format("/opt/cloud/bin/prepare_pxe.sh %s %s %s %s %s %s", tuple.get(1), tuple.get(2), profile.getTemplate().getUuid(),
234234
String.format("01-%s", nic.getMacAddress().replaceAll(":", "-")).toLowerCase(), tuple.get(0), nic.getMacAddress().toLowerCase());
235235
s_logger.debug(String.format("prepare pxe on virtual router[ip:%s], cmd: %s", mgmtNic.getIp4Address(), cmd));
236236
Pair<Boolean, String> ret = SshHelper.sshExecute(mgmtNic.getIp4Address(), 3922, "root", getSystemVMKeyFile(), null, cmd);
@@ -239,7 +239,7 @@ private boolean preparePxeInAdvancedZone(VirtualMachineProfile profile, NicProfi
239239
}
240240

241241
//String internalServerIp = "10.223.110.231";
242-
cmd = String.format("/usr/bin/baremetal_snat.sh %s %s %s", mgmtNic.getIp4Address(), internalServerIp, mgmtNic.getGateway());
242+
cmd = String.format("/opt/cloud/bin/baremetal_snat.sh %s %s %s", mgmtNic.getIp4Address(), internalServerIp, mgmtNic.getGateway());
243243
s_logger.debug(String.format("prepare SNAT on virtual router[ip:%s], cmd: %s", mgmtNic.getIp4Address(), cmd));
244244
ret = SshHelper.sshExecute(mgmtNic.getIp4Address(), 3922, "root", getSystemVMKeyFile(), null, cmd);
245245
if (!ret.first()) {

systemvm/patches/debian/config/etc/rc.local

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ then
4242
echo 1000000 > /proc/sys/net/nf_conntrack_max
4343
fi
4444

45-
python /usr/bin/baremetal-vr.py &
45+
python /opt/cloud/bin/baremetal-vr.py &
4646

4747
date > /var/cache/cloud/boot_up_done
4848
logger -t cloud "Boot up process done"
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
__author__ = 'frank'
2+
3+
import subprocess
4+
import urllib
5+
import hmac
6+
import hashlib
7+
import base64
8+
import traceback
9+
import logging
10+
11+
from flask import Flask
12+
13+
app = Flask(__name__)
14+
15+
logger = logging.getLogger('baremetal-vr')
16+
hdlr = logging.FileHandler('/var/log/baremetal-vr.log')
17+
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
18+
hdlr.setFormatter(formatter)
19+
logger.addHandler(hdlr)
20+
logger.setLevel(logging.WARNING)
21+
22+
class ShellCmd(object):
23+
'''
24+
classdocs
25+
'''
26+
def __init__(self, cmd, workdir=None, pipe=True):
27+
'''
28+
Constructor
29+
'''
30+
self.cmd = cmd
31+
if pipe:
32+
self.process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, executable='/bin/sh', cwd=workdir)
33+
else:
34+
self.process = subprocess.Popen(cmd, shell=True, executable='/bin/sh', cwd=workdir)
35+
36+
self.stdout = None
37+
self.stderr = None
38+
self.return_code = None
39+
40+
def __call__(self, is_exception=True):
41+
(self.stdout, self.stderr) = self.process.communicate()
42+
if is_exception and self.process.returncode != 0:
43+
err = []
44+
err.append('failed to execute shell command: %s' % self.cmd)
45+
err.append('return code: %s' % self.process.returncode)
46+
err.append('stdout: %s' % self.stdout)
47+
err.append('stderr: %s' % self.stderr)
48+
raise Exception('\n'.join(err))
49+
50+
self.return_code = self.process.returncode
51+
return self.stdout
52+
53+
def shell(cmd):
54+
return ShellCmd(cmd)()
55+
56+
57+
class Server(object):
58+
CMDLINE = '/var/cache/cloud/cmdline'
59+
def __init__(self):
60+
self.apikey = None
61+
self.secretkey = None
62+
self.mgmtIp = None
63+
self.mgmtPort = None
64+
65+
def _get_credentials(self):
66+
if not self.apikey or not self.secretkey:
67+
with open(self.CMDLINE, 'r') as fd:
68+
cmdline = fd.read()
69+
for p in cmdline.split():
70+
if 'baremetalnotificationsecuritykey' in p:
71+
self.secretkey = p.split("=")[1]
72+
if 'baremetalnotificationapikey' in p:
73+
self.apikey = p.split("=")[1]
74+
75+
if not self.apikey:
76+
raise Exception('cannot find baremetalnotificationapikey in %s' % Server.CMDLINE)
77+
if not self.secretkey:
78+
raise Exception('cannot find baremetalnotificationsecuritykey in %s' % Server.CMDLINE)
79+
80+
return self.apikey, self.secretkey
81+
82+
def _get_mgmt_ip(self):
83+
if not self.mgmtIp:
84+
with open(self.CMDLINE, 'r') as fd:
85+
cmdline = fd.read()
86+
for p in cmdline.split():
87+
if 'host' in p:
88+
self.mgmtIp = p.split("=")[1]
89+
break
90+
91+
if not self.mgmtIp:
92+
raise Exception('cannot find host in %s' % Server.CMDLINE)
93+
94+
return self.mgmtIp
95+
96+
def _get_mgmt_port(self):
97+
if not self.mgmtPort:
98+
with open(self.CMDLINE, 'r') as fd:
99+
cmdline = fd.read()
100+
for p in cmdline.split():
101+
if 'port' in p:
102+
self.mgmtPort = p.split("=")[1]
103+
break
104+
105+
if not self.mgmtIp:
106+
raise Exception('cannot find port in %s' % Server.CMDLINE)
107+
108+
return self.mgmtPort
109+
110+
def _make_sign(self, mac):
111+
apikey, secretkey = self._get_credentials()
112+
reqs = {
113+
"apiKey": apikey,
114+
"command": 'notifyBaremetalProvisionDone',
115+
"mac": mac
116+
}
117+
118+
request = zip(reqs.keys(), reqs.values())
119+
request.sort(key=lambda x: str.lower(x[0]))
120+
hashStr = "&".join(["=".join([str.lower(r[0]), str.lower(urllib.quote_plus(str(r[1]))).replace("+", "%20").replace('=', '%3d')]) for r in request])
121+
sig = urllib.quote_plus(base64.encodestring(hmac.new(secretkey, hashStr, hashlib.sha1).digest()).strip())
122+
return sig
123+
124+
def notify_provisioning_done(self, mac):
125+
sig = self._make_sign(mac)
126+
cmd = 'http://%s:%s/client/api?command=notifyBaremetalProvisionDone&mac=%s&apiKey=%s&signature=%s' % (self._get_mgmt_ip(), self._get_mgmt_port(), mac, self.apikey, sig)
127+
shell("curl -X GET '%s'" % cmd)
128+
return ''
129+
130+
server = None
131+
132+
@app.route('/baremetal/provisiondone/<mac>', methods=['GET'])
133+
def notify_provisioning_done(mac):
134+
try:
135+
return server.notify_provisioning_done(mac)
136+
except:
137+
logger.warn(traceback.format_exc())
138+
return ''
139+
140+
141+
if __name__ == '__main__':
142+
global server
143+
server = Server()
144+
shell("iptables-save | grep -- '-A INPUT -i eth0 -p tcp -m tcp --dport 10086 -j ACCEPT' > /dev/null || iptables -I INPUT -i eth0 -p tcp -m tcp --dport 10086 -j ACCEPT")
145+
app.run(host='0.0.0.0', port=10086, debug=True)

scripts/network/ping/baremetal_snat.sh renamed to systemvm/patches/debian/config/opt/cloud/bin/baremetal_snat.sh

File renamed without changes.

scripts/network/ping/prepare_pxe.sh renamed to systemvm/patches/debian/config/opt/cloud/bin/prepare_pxe.sh

File renamed without changes.

0 commit comments

Comments
 (0)