Repository: cloudstack Updated Branches: refs/heads/master aed36c277 -> 01dada100
CLOUDSTACK-6278 Baremetal Advanced Networking support Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/01dada10 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/01dada10 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/01dada10 Branch: refs/heads/master Commit: 01dada100a34f42520446a64e02bd8eb2cf4e7fe Parents: aed36c2 Author: Frank Zhang <frank.zh...@citrix.com> Authored: Mon Oct 6 15:46:36 2014 -0700 Committer: Frank Zhang <frank.zh...@citrix.com> Committed: Mon Oct 6 16:03:19 2014 -0700 ---------------------------------------------------------------------- .gitignore | 1 - .../BaremetalKickStartServiceImpl.java | 4 +- scripts/network/ping/baremetal_snat.sh | 54 ------- scripts/network/ping/prepare_pxe.sh | 77 ---------- systemvm/patches/debian/config/etc/rc.local | 2 +- .../debian/config/opt/cloud/bin/baremetal-vr.py | 145 +++++++++++++++++++ .../config/opt/cloud/bin/baremetal_snat.sh | 54 +++++++ .../debian/config/opt/cloud/bin/prepare_pxe.sh | 77 ++++++++++ 8 files changed, 279 insertions(+), 135 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/01dada10/.gitignore ---------------------------------------------------------------------- diff --git a/.gitignore b/.gitignore index fdac72e..4ce64ef 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,6 @@ build/replace.properties build/build.number -bin/ .lock-wscript .waf-* waf-* http://git-wip-us.apache.org/repos/asf/cloudstack/blob/01dada10/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java index 16fc460..7f6b0bf 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java @@ -230,7 +230,7 @@ public class BaremetalKickStartServiceImpl extends BareMetalPxeServiceBase imple } 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()); 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); @@ -239,7 +239,7 @@ public class BaremetalKickStartServiceImpl extends BareMetalPxeServiceBase imple } //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)); ret = SshHelper.sshExecute(mgmtNic.getIp4Address(), 3922, "root", getSystemVMKeyFile(), null, cmd); if (!ret.first()) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/01dada10/scripts/network/ping/baremetal_snat.sh ---------------------------------------------------------------------- diff --git a/scripts/network/ping/baremetal_snat.sh b/scripts/network/ping/baremetal_snat.sh deleted file mode 100755 index 22e5669..0000000 --- a/scripts/network/ping/baremetal_snat.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -#Licensed to the Apache Software Foundation (ASF) under one -#or more contributor license agreements. See the NOTICE file -#distributed with this work for additional information -#regarding copyright ownership. The ASF licenses this file -#to you under the Apache License, Version 2.0 (the -#"License"); you may not use this file except in compliance -#with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -#Unless required by applicable law or agreed to in writing, -#software distributed under the License is distributed on an -#"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -#KIND, either express or implied. See the License for the -#specific language governing permissions and limitations -#under the License. - -set +u - -mgmt_nic_ip=$1 -internal_server_ip=$2 -gateway_ip=$3 - -ip route | grep "$internal_server_ip" > /dev/null - -if [ $? -ne 0 ]; then - ip route add $internal_server_ip via $gateway_ip -fi - -iptables-save | grep -- "-A POSTROUTING -d $internal_server_ip" > /dev/null - -if [ $? -ne 0 ]; then - iptables -t nat -A POSTROUTING -d $internal_server_ip -j SNAT --to-source $mgmt_nic_ip -fi - - -iptables-save | grep -- "-A INPUT -i eth0 -p udp -m udp --dport 69 -j ACCEPT" > /dev/null -if [ $? -ne 0 ]; then - iptables -I INPUT -i eth0 -p udp -m udp --dport 69 -j ACCEPT -fi - -iptables-save | grep -- "-A FORWARD -i eth1 -o eth0 -j ACCEPT" > /dev/null -if [ $? -ne 0 ]; then - iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT -fi - -rule="-A FORWARD -d $internal_server_ip/32 -i eth0 -o eth1 -j ACCEPT" -iptables-save | grep -- "$rule" > /dev/null -if [ $? -ne 0 ]; then - iptables -I FORWARD -d $internal_server_ip/32 -i eth0 -o eth1 -j ACCEPT -fi - http://git-wip-us.apache.org/repos/asf/cloudstack/blob/01dada10/scripts/network/ping/prepare_pxe.sh ---------------------------------------------------------------------- diff --git a/scripts/network/ping/prepare_pxe.sh b/scripts/network/ping/prepare_pxe.sh deleted file mode 100755 index 5bc1a93..0000000 --- a/scripts/network/ping/prepare_pxe.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/sh -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# # regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -set +u - -err_exit() { - echo $1 - exit 1 -} - -success() { - exit 0 -} - -TFTP_ROOT='/opt/tftpboot' -PXELINUX_CFG_DIR='/opt/tftpboot/pxelinux.cfg' - -kernel_nfs_path=$1 -kernel_file_name=`basename $kernel_nfs_path` -initrd_nfs_path=$2 -initrd_file_name=`basename $initrd_nfs_path` -tmpt_uuid=$3 -pxe_cfg_filename=$4 -ks_file=$5 - -kernel_path=$tmpt_uuid/$kernel_file_name -initrd_path=$tmpt_uuid/$initrd_file_name - -cat > $PXELINUX_CFG_DIR/$pxe_cfg_filename <<EOF -DEFAULT default -PROMPT 1 -TIMEOUT 26 -DISPLAY boot.msg -LABEL default -KERNEL $kernel_path -APPEND ramdisk_size=66000 initrd=$initrd_path ks=$ks_file - -EOF - -tmpt_dir=$TFTP_ROOT/$tmpt_uuid -if [ -d $tmpt_dir ]; then - success -fi - -mkdir -p $tmpt_dir - -mnt_path=/tmp/$(uuid) - -mkdir -p $mnt_path -mount `dirname $kernel_nfs_path` $mnt_path -cp -f $mnt_path/$kernel_file_name $tmpt_dir/$kernel_file_name -umount $mnt_path - -mount `dirname $initrd_nfs_path` $mnt_path -cp -f $mnt_path/$initrd_file_name $tmpt_dir/$initrd_file_name -umount $mnt_path - -success - - http://git-wip-us.apache.org/repos/asf/cloudstack/blob/01dada10/systemvm/patches/debian/config/etc/rc.local ---------------------------------------------------------------------- diff --git a/systemvm/patches/debian/config/etc/rc.local b/systemvm/patches/debian/config/etc/rc.local index 78fb5de..23e913e 100755 --- a/systemvm/patches/debian/config/etc/rc.local +++ b/systemvm/patches/debian/config/etc/rc.local @@ -42,7 +42,7 @@ then echo 1000000 > /proc/sys/net/nf_conntrack_max fi -python /usr/bin/baremetal-vr.py & +python /opt/cloud/bin/baremetal-vr.py & date > /var/cache/cloud/boot_up_done logger -t cloud "Boot up process done" http://git-wip-us.apache.org/repos/asf/cloudstack/blob/01dada10/systemvm/patches/debian/config/opt/cloud/bin/baremetal-vr.py ---------------------------------------------------------------------- diff --git a/systemvm/patches/debian/config/opt/cloud/bin/baremetal-vr.py b/systemvm/patches/debian/config/opt/cloud/bin/baremetal-vr.py new file mode 100755 index 0000000..05188d4 --- /dev/null +++ b/systemvm/patches/debian/config/opt/cloud/bin/baremetal-vr.py @@ -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) http://git-wip-us.apache.org/repos/asf/cloudstack/blob/01dada10/systemvm/patches/debian/config/opt/cloud/bin/baremetal_snat.sh ---------------------------------------------------------------------- diff --git a/systemvm/patches/debian/config/opt/cloud/bin/baremetal_snat.sh b/systemvm/patches/debian/config/opt/cloud/bin/baremetal_snat.sh new file mode 100755 index 0000000..22e5669 --- /dev/null +++ b/systemvm/patches/debian/config/opt/cloud/bin/baremetal_snat.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +#Licensed to the Apache Software Foundation (ASF) under one +#or more contributor license agreements. See the NOTICE file +#distributed with this work for additional information +#regarding copyright ownership. The ASF licenses this file +#to you under the Apache License, Version 2.0 (the +#"License"); you may not use this file except in compliance +#with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +#Unless required by applicable law or agreed to in writing, +#software distributed under the License is distributed on an +#"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +#KIND, either express or implied. See the License for the +#specific language governing permissions and limitations +#under the License. + +set +u + +mgmt_nic_ip=$1 +internal_server_ip=$2 +gateway_ip=$3 + +ip route | grep "$internal_server_ip" > /dev/null + +if [ $? -ne 0 ]; then + ip route add $internal_server_ip via $gateway_ip +fi + +iptables-save | grep -- "-A POSTROUTING -d $internal_server_ip" > /dev/null + +if [ $? -ne 0 ]; then + iptables -t nat -A POSTROUTING -d $internal_server_ip -j SNAT --to-source $mgmt_nic_ip +fi + + +iptables-save | grep -- "-A INPUT -i eth0 -p udp -m udp --dport 69 -j ACCEPT" > /dev/null +if [ $? -ne 0 ]; then + iptables -I INPUT -i eth0 -p udp -m udp --dport 69 -j ACCEPT +fi + +iptables-save | grep -- "-A FORWARD -i eth1 -o eth0 -j ACCEPT" > /dev/null +if [ $? -ne 0 ]; then + iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT +fi + +rule="-A FORWARD -d $internal_server_ip/32 -i eth0 -o eth1 -j ACCEPT" +iptables-save | grep -- "$rule" > /dev/null +if [ $? -ne 0 ]; then + iptables -I FORWARD -d $internal_server_ip/32 -i eth0 -o eth1 -j ACCEPT +fi + http://git-wip-us.apache.org/repos/asf/cloudstack/blob/01dada10/systemvm/patches/debian/config/opt/cloud/bin/prepare_pxe.sh ---------------------------------------------------------------------- diff --git a/systemvm/patches/debian/config/opt/cloud/bin/prepare_pxe.sh b/systemvm/patches/debian/config/opt/cloud/bin/prepare_pxe.sh new file mode 100755 index 0000000..5bc1a93 --- /dev/null +++ b/systemvm/patches/debian/config/opt/cloud/bin/prepare_pxe.sh @@ -0,0 +1,77 @@ +#!/bin/sh +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# # regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +set +u + +err_exit() { + echo $1 + exit 1 +} + +success() { + exit 0 +} + +TFTP_ROOT='/opt/tftpboot' +PXELINUX_CFG_DIR='/opt/tftpboot/pxelinux.cfg' + +kernel_nfs_path=$1 +kernel_file_name=`basename $kernel_nfs_path` +initrd_nfs_path=$2 +initrd_file_name=`basename $initrd_nfs_path` +tmpt_uuid=$3 +pxe_cfg_filename=$4 +ks_file=$5 + +kernel_path=$tmpt_uuid/$kernel_file_name +initrd_path=$tmpt_uuid/$initrd_file_name + +cat > $PXELINUX_CFG_DIR/$pxe_cfg_filename <<EOF +DEFAULT default +PROMPT 1 +TIMEOUT 26 +DISPLAY boot.msg +LABEL default +KERNEL $kernel_path +APPEND ramdisk_size=66000 initrd=$initrd_path ks=$ks_file + +EOF + +tmpt_dir=$TFTP_ROOT/$tmpt_uuid +if [ -d $tmpt_dir ]; then + success +fi + +mkdir -p $tmpt_dir + +mnt_path=/tmp/$(uuid) + +mkdir -p $mnt_path +mount `dirname $kernel_nfs_path` $mnt_path +cp -f $mnt_path/$kernel_file_name $tmpt_dir/$kernel_file_name +umount $mnt_path + +mount `dirname $initrd_nfs_path` $mnt_path +cp -f $mnt_path/$initrd_file_name $tmpt_dir/$initrd_file_name +umount $mnt_path + +success + +