CLOUDSTACK-6278

Baremetal Advanced Networking support
This commit is contained in:
Frank Zhang 2014-10-06 15:46:36 -07:00
parent aed36c2776
commit 01dada100a
6 changed files with 148 additions and 4 deletions

1
.gitignore vendored
View File

@ -17,7 +17,6 @@
build/replace.properties build/replace.properties
build/build.number build/build.number
bin/
.lock-wscript .lock-wscript
.waf-* .waf-*
waf-* waf-*

View File

@ -230,7 +230,7 @@ public class BaremetalKickStartServiceImpl extends BareMetalPxeServiceBase imple
} }
List<String> tuple = parseKickstartUrl(profile); List<String> tuple = parseKickstartUrl(profile);
String cmd = String.format("/usr/bin/prepare_pxe.sh %s %s %s %s %s %s", tuple.get(1), tuple.get(2), profile.getTemplate().getUuid(), 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(),
String.format("01-%s", nic.getMacAddress().replaceAll(":", "-")).toLowerCase(), tuple.get(0), nic.getMacAddress().toLowerCase()); String.format("01-%s", nic.getMacAddress().replaceAll(":", "-")).toLowerCase(), tuple.get(0), nic.getMacAddress().toLowerCase());
s_logger.debug(String.format("prepare pxe on virtual router[ip:%s], cmd: %s", mgmtNic.getIp4Address(), cmd)); s_logger.debug(String.format("prepare pxe on virtual router[ip:%s], cmd: %s", mgmtNic.getIp4Address(), cmd));
Pair<Boolean, String> ret = SshHelper.sshExecute(mgmtNic.getIp4Address(), 3922, "root", getSystemVMKeyFile(), null, cmd); Pair<Boolean, String> ret = SshHelper.sshExecute(mgmtNic.getIp4Address(), 3922, "root", getSystemVMKeyFile(), null, cmd);
@ -239,7 +239,7 @@ public class BaremetalKickStartServiceImpl extends BareMetalPxeServiceBase imple
} }
//String internalServerIp = "10.223.110.231"; //String internalServerIp = "10.223.110.231";
cmd = String.format("/usr/bin/baremetal_snat.sh %s %s %s", mgmtNic.getIp4Address(), internalServerIp, mgmtNic.getGateway()); cmd = String.format("/opt/cloud/bin/baremetal_snat.sh %s %s %s", mgmtNic.getIp4Address(), internalServerIp, mgmtNic.getGateway());
s_logger.debug(String.format("prepare SNAT on virtual router[ip:%s], cmd: %s", mgmtNic.getIp4Address(), cmd)); s_logger.debug(String.format("prepare SNAT on virtual router[ip:%s], cmd: %s", mgmtNic.getIp4Address(), cmd));
ret = SshHelper.sshExecute(mgmtNic.getIp4Address(), 3922, "root", getSystemVMKeyFile(), null, cmd); ret = SshHelper.sshExecute(mgmtNic.getIp4Address(), 3922, "root", getSystemVMKeyFile(), null, cmd);
if (!ret.first()) { if (!ret.first()) {

View File

@ -42,7 +42,7 @@ then
echo 1000000 > /proc/sys/net/nf_conntrack_max echo 1000000 > /proc/sys/net/nf_conntrack_max
fi fi
python /usr/bin/baremetal-vr.py & python /opt/cloud/bin/baremetal-vr.py &
date > /var/cache/cloud/boot_up_done date > /var/cache/cloud/boot_up_done
logger -t cloud "Boot up process done" logger -t cloud "Boot up process done"

View File

@ -0,0 +1,145 @@
__author__ = 'frank'
import subprocess
import urllib
import hmac
import hashlib
import base64
import traceback
import logging
from flask import Flask
app = Flask(__name__)
logger = logging.getLogger('baremetal-vr')
hdlr = logging.FileHandler('/var/log/baremetal-vr.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.WARNING)
class ShellCmd(object):
'''
classdocs
'''
def __init__(self, cmd, workdir=None, pipe=True):
'''
Constructor
'''
self.cmd = cmd
if pipe:
self.process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, executable='/bin/sh', cwd=workdir)
else:
self.process = subprocess.Popen(cmd, shell=True, executable='/bin/sh', cwd=workdir)
self.stdout = None
self.stderr = None
self.return_code = None
def __call__(self, is_exception=True):
(self.stdout, self.stderr) = self.process.communicate()
if is_exception and self.process.returncode != 0:
err = []
err.append('failed to execute shell command: %s' % self.cmd)
err.append('return code: %s' % self.process.returncode)
err.append('stdout: %s' % self.stdout)
err.append('stderr: %s' % self.stderr)
raise Exception('\n'.join(err))
self.return_code = self.process.returncode
return self.stdout
def shell(cmd):
return ShellCmd(cmd)()
class Server(object):
CMDLINE = '/var/cache/cloud/cmdline'
def __init__(self):
self.apikey = None
self.secretkey = None
self.mgmtIp = None
self.mgmtPort = None
def _get_credentials(self):
if not self.apikey or not self.secretkey:
with open(self.CMDLINE, 'r') as fd:
cmdline = fd.read()
for p in cmdline.split():
if 'baremetalnotificationsecuritykey' in p:
self.secretkey = p.split("=")[1]
if 'baremetalnotificationapikey' in p:
self.apikey = p.split("=")[1]
if not self.apikey:
raise Exception('cannot find baremetalnotificationapikey in %s' % Server.CMDLINE)
if not self.secretkey:
raise Exception('cannot find baremetalnotificationsecuritykey in %s' % Server.CMDLINE)
return self.apikey, self.secretkey
def _get_mgmt_ip(self):
if not self.mgmtIp:
with open(self.CMDLINE, 'r') as fd:
cmdline = fd.read()
for p in cmdline.split():
if 'host' in p:
self.mgmtIp = p.split("=")[1]
break
if not self.mgmtIp:
raise Exception('cannot find host in %s' % Server.CMDLINE)
return self.mgmtIp
def _get_mgmt_port(self):
if not self.mgmtPort:
with open(self.CMDLINE, 'r') as fd:
cmdline = fd.read()
for p in cmdline.split():
if 'port' in p:
self.mgmtPort = p.split("=")[1]
break
if not self.mgmtIp:
raise Exception('cannot find port in %s' % Server.CMDLINE)
return self.mgmtPort
def _make_sign(self, mac):
apikey, secretkey = self._get_credentials()
reqs = {
"apiKey": apikey,
"command": 'notifyBaremetalProvisionDone',
"mac": mac
}
request = zip(reqs.keys(), reqs.values())
request.sort(key=lambda x: str.lower(x[0]))
hashStr = "&".join(["=".join([str.lower(r[0]), str.lower(urllib.quote_plus(str(r[1]))).replace("+", "%20").replace('=', '%3d')]) for r in request])
sig = urllib.quote_plus(base64.encodestring(hmac.new(secretkey, hashStr, hashlib.sha1).digest()).strip())
return sig
def notify_provisioning_done(self, mac):
sig = self._make_sign(mac)
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)
shell("curl -X GET '%s'" % cmd)
return ''
server = None
@app.route('/baremetal/provisiondone/<mac>', methods=['GET'])
def notify_provisioning_done(mac):
try:
return server.notify_provisioning_done(mac)
except:
logger.warn(traceback.format_exc())
return ''
if __name__ == '__main__':
global server
server = Server()
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")
app.run(host='0.0.0.0', port=10086, debug=True)