Add missing Baremetal security_group_agent java part

Change security_group_agent python side in line with default security
group rules change in 4.2
This commit is contained in:
Frank.Zhang 2013-10-07 18:03:12 -07:00
parent e256794a35
commit d31dcdfd92
8 changed files with 1150 additions and 318 deletions

View File

@ -16,222 +16,369 @@
# under the License.
#
# Automatically generated by addcopyright.py at 01/29/2013
'''
Created on Jan 2, 2013
@author: frank
'''
import cherrypy
import sglib
import xmlobject
import types
import uuid
import os.path
import sys
import os
class SGRule(object):
def __init__(self):
self.protocol = None
self.start_port = None
self.end_port = None
self.allowed_ips = []
class IPSet(object):
IPSET_TYPE = 'hash:ip'
def __init__(self, setname, ips):
self.ips = ips
self.name = setname
def create(self):
tmpname = str(uuid.uuid4()).replace('-', '')[0:30]
sglib.ShellCmd('ipset -N %s %s' % (tmpname, self.IPSET_TYPE))()
try:
for ip in self.ips:
sglib.ShellCmd('ipset -A %s %s' % (tmpname, ip))()
try:
sglib.ShellCmd('ipset -N %s %s' % (self.name, self.IPSET_TYPE))()
cherrypy.log('created new ipset: %s' % self.name)
except Exception:
cherrypy.log('%s already exists, no need to create new' % self.name)
finally:
sglib.ShellCmd('ipset -W %s %s' % (tmpname, self.name))()
sglib.ShellCmd('ipset -F %s' % tmpname)()
sglib.ShellCmd('ipset -X %s' % tmpname)()
@staticmethod
def destroy_sets(sets_to_keep):
sets = sglib.ShellCmd('ipset list')()
for s in sets.split('\n'):
if 'Name:' in s:
set_name = s.split(':', 1)[1].strip()
if not set_name in sets_to_keep:
sglib.ShellCmd('ipset destroy %s' % set_name)()
cherrypy.log('destroyed unused ipset: %s' % set_name)
class SGAgent(object):
def __init__(self):
pass
def _self_list(self, obj):
if isinstance(obj, types.ListType):
return obj
else:
return [obj]
def set_rules(self, req):
body = req.body
doc = xmlobject.loads(body)
vm_name = doc.vmName.text_
vm_id = doc.vmId.text_
vm_ip = doc.vmIp.text_
vm_mac = doc.vmMac.text_
sig = doc.signature.text_
seq = doc.sequenceNumber.text_
def parse_rules(rules, lst):
for i in self._self_list(rules):
r = SGRule()
r.protocol = i.protocol.text_
r.start_port = i.startPort.text_
r.end_port = i.endPort.text_
if hasattr(i, 'ip'):
for ip in self._self_list(i.ip):
r.allowed_ips.append(ip.text_)
lst.append(r)
i_rules = []
if hasattr(doc, 'ingressRules'):
parse_rules(doc.ingressRules, i_rules)
e_rules = []
if hasattr(doc, 'egressRules'):
parse_rules(doc.egressRules, e_rules)
def create_chain(name):
try:
sglib.ShellCmd('iptables -F %s' % name)()
except Exception:
sglib.ShellCmd('iptables -N %s' % name)()
def apply_rules(rules, chainname, direction, action, current_set_names):
create_chain(chainname)
for r in i_rules:
allow_any = False
if '0.0.0.0/0' in r.allowed_ips:
allow_any = True
r.allowed_ips.remove('0.0.0.0/0')
if r.allowed_ips:
setname = '_'.join([chainname, r.protocol, r.start_port, r.end_port])
ipset = IPSet(setname, r.allowed_ips)
ipset.create()
current_set_names.append(setname)
if r.protocol == 'all':
cmd = ['iptables -I', chainname, '-m state --state NEW -m set --set', setname, direction, '-j', action]
sglib.ShellCmd(' '.join(cmd))()
elif r.protocol != 'icmp':
port_range = ":".join([r.start_port, r.end_port])
cmd = ['iptables', '-I', chainname, '-p', r.protocol, '-m', r.protocol, '--dport', port_range, '-m state --state NEW -m set --set', setname, direction, '-j', action]
sglib.ShellCmd(' '.join(cmd))()
else:
port_range = "/".join([r.start_port, r.end_port])
if r.start_port == "-1":
port_range = "any"
cmd = ['iptables', '-I', i_chain_name, '-p', 'icmp', '--icmp-type', port_range, '-m set --set', setname, direction, '-j', action]
sglib.ShellCmd(' '.join(cmd))()
if allow_any and r.protocol != 'all':
if r.protocol != 'icmp':
port_range = ":".join([r.start_port, r.end_port])
cmd = ['iptables', '-I', chainname, '-p', r.protocol, '-m', r.protocol, '--dport', port_range, '-m', 'state', '--state', 'NEW', '-j', action]
sglib.ShellCmd(' '.join(cmd))()
else:
port_range = "/".join([r.start_port, r.end_port])
if r.start_port == "-1":
port_range = "any"
cmd = ['iptables', '-I', i_chain_name, '-p', 'icmp', '--icmp-type', port_range, '-j', action]
sglib.ShellCmd(' '.join(cmd))()
current_sets = []
i_chain_name = vm_name + '-in'
apply_rules(i_rules, i_chain_name, 'src', 'ACCEPT', current_sets)
e_chain_name = vm_name + '-eg'
apply_rules(e_rules, e_chain_name, 'dst', 'RETURN', current_sets)
if e_rules:
sglib.ShellCmd('iptables -A %s -j RETURN' % e_chain_name)
else:
sglib.ShellCmd('iptables -A %s -j DROP' % e_chain_name)
sglib.ShellCmd('iptables -A %s -j DROP' % i_chain_name)
IPSet.destroy_sets(current_sets)
def echo(self, req):
cherrypy.log("echo: I am alive")
def index(self):
req = sglib.Request.from_cherrypy_request(cherrypy.request)
cmd_name = req.headers['command']
if not hasattr(self, cmd_name):
raise ValueError("SecurityGroupAgent doesn't have a method called '%s'" % cmd_name)
method = getattr(self, cmd_name)
return method(req)
index.exposed = True
@staticmethod
def start():
cherrypy.log.access_file = '/var/log/cs-securitygroup.log'
cherrypy.log.error_file = '/var/log/cs-securitygroup.log'
cherrypy.server.socket_host = '0.0.0.0'
cherrypy.server.socket_port = 9988
cherrypy.quickstart(SGAgent())
@staticmethod
def stop():
cherrypy.engine.exit()
PID_FILE = '/var/run/cssgagent.pid'
class SGAgentDaemon(sglib.Daemon):
def __init__(self):
super(SGAgentDaemon, self).__init__(PID_FILE)
self.is_stopped = False
self.agent = SGAgent()
sglib.Daemon.register_atexit_hook(self._do_stop)
def _do_stop(self):
if self.is_stopped:
return
self.is_stopped = True
self.agent.stop()
def run(self):
self.agent.start()
def stop(self):
self.agent.stop()
super(SGAgentDaemon, self).stop()
def main():
usage = 'usage: python -c "from security_group_agent import cs_sg_agent; cs_sg_agent.main()" start|stop|restart'
if len(sys.argv) != 2 or not sys.argv[1] in ['start', 'stop', 'restart']:
print usage
sys.exit(1)
cmd = sys.argv[1]
agentdaemon = SGAgentDaemon()
if cmd == 'start':
agentdaemon.start()
elif cmd == 'stop':
agentdaemon.stop()
else:
agentdaemon.restart()
sys.exit(0)
'''
Created on Jan 2, 2013
@author: frank
'''
import cherrypy
import sglib
import xmlobject
import types
import uuid
import os.path
import sys
import os
class SGRule(object):
def __init__(self):
self.protocol = None
self.start_port = None
self.end_port = None
self.allowed_ips = []
# iptables -D cannot handle rules having ipset match
# we have to delete these rules by line number that's why I introduce
# this class that maintains rules with their line number
class IptableChain(object):
def __init__(self):
self.name = None
self.rules = {}
def delete_rule_by_line_number(self, num):
if str(num) not in self.rules.values():
return
sglib.ShellCmd('iptables -D %s %s' % (self.name, num))()
@staticmethod
def from_iptable_lists():
txt= sglib.ShellCmd('iptables --list --line-number')()
blocks = txt.split('\n')
def is_rule_line(rule):
def is_number(n):
try:
int(n)
return True
except Exception:
return False
words = rule.split()
return is_number(words[0])
current_chain = None
chains = []
for line in blocks:
line = line.strip()
if line == '':
continue
if line.startswith('Chain'):
current_chain = IptableChain()
current_chain.name = line.split()[1]
chains.append(current_chain)
continue
if not is_rule_line(line):
continue
specs = line.split(None, 6)
if len(specs) == 7:
# e.g '1 RETURN tcp -- anywhere anywhere tcp dpt:https state NEW match-set i-4-32-VM-eg_tcp_443_443 dst'
# the last part is spec, using spec as key
current_chain.rules[specs[-1]] = specs[0]
else:
# e.g '3 DROP all -- anywhere anywhere'
# no spec, using target as key
current_chain.rules[specs[1]] = specs[0]
return chains
class IPSet(object):
IPSET_TYPE = 'hash:net'
def __init__(self, setname, ips):
self.ips = ips
self.name = setname
def create(self):
tmpname = str(uuid.uuid4()).replace('-', '')[0:30]
sglib.ShellCmd('ipset -N %s %s' % (tmpname, self.IPSET_TYPE))()
try:
for ip in self.ips:
sglib.ShellCmd('ipset -A %s %s' % (tmpname, ip))()
try:
sglib.ShellCmd('ipset -N %s %s' % (self.name, self.IPSET_TYPE))()
cherrypy.log('created ip set as: \nname: %s\nips: %s\n' % (self.name, self.ips))
except Exception:
cherrypy.log('%s already exists, no need to create new' % self.name)
finally:
sglib.ShellCmd('ipset -W %s %s' % (tmpname, self.name))()
sglib.ShellCmd('ipset -F %s' % tmpname)()
sglib.ShellCmd('ipset -X %s' % tmpname)()
@staticmethod
def destroy_sets_not_in(sets_to_keep):
def remove_iptable_rules_having_set_name(setname):
chains = IptableChain.from_iptable_lists()
for c in chains:
for spec, linenum in c.rules.items():
if setname in spec:
c.delete_rule_by_line_number(linenum)
# as line number will change each time after deleting a rule,
# we have to retrieve all chains again
# this shows that old solid tools also have old bad user experience
remove_iptable_rules_having_set_name(setname)
return
sets = sglib.ShellCmd('ipset list')()
for s in sets.split('\n'):
if 'Name:' in s:
set_name = s.split(':', 1)[1].strip()
if not set_name in sets_to_keep:
remove_iptable_rules_having_set_name(set_name)
sglib.ShellCmd('ipset destroy %s' % set_name)()
cherrypy.log('destroyed unused ipset: %s' % set_name)
class SGAgent(object):
RULE_HISTORY_PTH = '/var/lib/cloudstack/cs-agent.history'
def __init__(self):
history_dir = os.path.dirname(self.RULE_HISTORY_PTH)
if not os.path.exists(history_dir):
os.makedirs(history_dir, 0755)
def _self_list(self, obj):
if isinstance(obj, types.ListType):
return obj
else:
return [obj]
def sync(self, req):
if not os.path.exists(self.RULE_HISTORY_PTH):
return ''
with open(self.RULE_HISTORY_PTH, 'r') as fd:
history = fd.read()
cherrypy.log('sync: %s' % history)
return history
def create_rule_if_not_exists(self, rule):
out = sglib.ShellCmd('iptables-save')()
if rule in out:
return
sglib.ShellCmd('iptables %s' % rule)()
@sglib.lock('set_rules')
def set_rules(self, req):
body = req.body
cherrypy.log('received security group rules as:\n%s\n' % body)
doc = xmlobject.loads(body)
vm_name = doc.vmName.text_
vm_id = doc.vmId.text_
vm_ip = doc.vmIp.text_
vm_mac = doc.vmMac.text_
sig = doc.signature.text_
seq = doc.sequenceNumber.text_
def parse_rules(rules, lst):
for i in self._self_list(rules):
r = SGRule()
r.protocol = i.protocol.text_
r.start_port = i.startPort.text_
r.end_port = i.endPort.text_
if hasattr(i, 'ip'):
for ip in self._self_list(i.ip):
r.allowed_ips.append(ip.text_)
lst.append(r)
i_rules = []
if hasattr(doc, 'ingressRules'):
parse_rules(doc.ingressRules, i_rules)
e_rules = []
if hasattr(doc, 'egressRules'):
parse_rules(doc.egressRules, e_rules)
def create_chain(name):
try:
sglib.ShellCmd('iptables -F %s' % name)()
except Exception:
sglib.ShellCmd('iptables -N %s' % name)()
def delete_chain(name):
try:
sglib.ShellCmd('iptables -F %s' % name)()
try:
sglib.ShellCmd('iptables -D INPUT -j %s' % name)()
except:
pass
try:
sglib.ShellCmd('iptables -D OUTPUT -j %s' % name)()
except:
pass
try:
sglib.ShellCmd('iptables -D %s -p tcp --dport 9988 -j ACCEPT' % name)()
except:
pass
sglib.ShellCmd('iptables -X %s' % name)()
cherrypy.log('deleted chain %s' % name)
except:
# safely ignore error
pass
def apply_rules(rules, chainname, direction, action, current_set_names):
for r in rules:
allow_any = False
if '0.0.0.0/0' in r.allowed_ips:
allow_any = True
r.allowed_ips.remove('0.0.0.0/0')
if r.allowed_ips:
setname = '_'.join([chainname, r.protocol, r.start_port, r.end_port])
ipset = IPSet(setname, r.allowed_ips)
ipset.create()
current_set_names.append(setname)
if r.protocol == 'all':
cmd = ['iptables -I', chainname, '-m state --state NEW -m set --set', setname, direction, '-j', action]
sglib.ShellCmd(' '.join(cmd))()
elif r.protocol != 'icmp':
port_range = ":".join([r.start_port, r.end_port])
cmd = ['iptables', '-I', chainname, '-p', r.protocol, '-m', r.protocol, '--dport', port_range, '-m state --state NEW -m set --set', setname, direction, '-j', action]
sglib.ShellCmd(' '.join(cmd))()
else:
port_range = "/".join([r.start_port, r.end_port])
if r.start_port == "-1":
port_range = "any"
cmd = ['iptables', '-I', chainname, '-p', 'icmp', '--icmp-type', port_range, '-m set --set', setname, direction, '-j', action]
sglib.ShellCmd(' '.join(cmd))()
if allow_any and r.protocol != 'all':
if r.protocol != 'icmp':
port_range = ":".join([r.start_port, r.end_port])
cmd = ['iptables', '-I', chainname, '-p', r.protocol, '-m', r.protocol, '--dport', port_range, '-m', 'state', '--state', 'NEW', '-j', action]
sglib.ShellCmd(' '.join(cmd))()
else:
port_range = "/".join([r.start_port, r.end_port])
if r.start_port == "-1":
port_range = "any"
cmd = ['iptables', '-I', chainname, '-p', 'icmp', '--icmp-type', port_range, '-j', action]
sglib.ShellCmd(' '.join(cmd))()
current_sets = []
i_chain_name = vm_name + '-in'
if i_rules:
create_chain(i_chain_name)
self.create_rule_if_not_exists('-A INPUT -j %s' % i_chain_name)
sglib.ShellCmd('iptables -A %s -p tcp --dport 9988 -j ACCEPT' % i_chain_name)()
sglib.ShellCmd('iptables -A %s -m state --state RELATED,ESTABLISHED -j ACCEPT' % i_chain_name)()
apply_rules(i_rules, i_chain_name, 'src', 'ACCEPT', current_sets)
sglib.ShellCmd('iptables -A %s -j DROP' % i_chain_name)()
else:
delete_chain(i_chain_name)
e_chain_name = vm_name + '-eg'
if e_rules:
create_chain(e_chain_name)
self.create_rule_if_not_exists('-A OUTPUT -j %s' % e_chain_name)
sglib.ShellCmd('iptables -A %s -m state --state RELATED,ESTABLISHED -j RETURN' % e_chain_name)()
apply_rules(e_rules, e_chain_name, 'dst', 'RETURN', current_sets)
sglib.ShellCmd('iptables -A %s -j DROP' % e_chain_name)
else:
delete_chain(e_chain_name)
IPSet.destroy_sets_not_in(current_sets)
history = ','.join([vm_name, vm_id, vm_ip, '_', sig, seq])
with open(self.RULE_HISTORY_PTH, 'w') as fd:
fd.write(history)
def echo(self, req):
cherrypy.log("echo: I am alive")
def index(self):
req = sglib.Request.from_cherrypy_request(cherrypy.request)
cmd_name = req.headers['command']
if not hasattr(self, cmd_name):
raise ValueError("SecurityGroupAgent doesn't have a method called '%s'" % cmd_name)
method = getattr(self, cmd_name)
return method(req)
index.exposed = True
@staticmethod
def start():
def prepare_default_rules():
sglib.ShellCmd('iptables --policy INPUT DROP')()
name = 'default-chain'
try:
sglib.ShellCmd('iptables -F %s' % name)()
except Exception:
sglib.ShellCmd('iptables -N %s' % name)()
sglib.ShellCmd('iptables -I INPUT -p tcp --dport 9988 -j ACCEPT')()
prepare_default_rules()
cherrypy.log.access_file = '/var/log/cs-securitygroup.log'
cherrypy.log.error_file = '/var/log/cs-securitygroup.log'
cherrypy.server.socket_host = '0.0.0.0'
cherrypy.server.socket_port = 9988
cherrypy.quickstart(SGAgent())
@staticmethod
def stop():
cherrypy.engine.exit()
PID_FILE = '/var/run/cssgagent.pid'
class SGAgentDaemon(sglib.Daemon):
def __init__(self):
super(SGAgentDaemon, self).__init__(PID_FILE)
self.is_stopped = False
self.agent = SGAgent()
sglib.Daemon.register_atexit_hook(self._do_stop)
def _do_stop(self):
if self.is_stopped:
return
self.is_stopped = True
self.agent.stop()
def run(self):
self.agent.start()
def stop(self):
self.agent.stop()
super(SGAgentDaemon, self).stop()
def main():
usage = 'usage: python -c "from security_group_agent import cs_sg_agent; cs_sg_agent.main()" start|stop|restart'
if len(sys.argv) != 2 or not sys.argv[1] in ['start', 'stop', 'restart']:
print usage
sys.exit(1)
cmd = sys.argv[1]
agentdaemon = SGAgentDaemon()
if cmd == 'start':
agentdaemon.start()
elif cmd == 'stop':
agentdaemon.stop()
else:
agentdaemon.restart()
sys.exit(0)

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python
# 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
@ -18,13 +17,55 @@
#
# Automatically generated by addcopyright.py at 01/29/2013
import sys, os, time, atexit
import traceback
#!/usr/bin/env python
import sys, os, time, atexit
import traceback
import subprocess
from signal import SIGTERM
from signal import SIGTERM,SIGKILL
import cherrypy
import copy
import weakref
import threading
import functools
_internal_lock = threading.RLock()
_locks = weakref.WeakValueDictionary()
def _get_lock(name):
with _internal_lock:
lock = _locks.get(name, threading.RLock())
if not name in _locks:
_locks[name] = lock
return lock
class NamedLock(object):
def __init__(self, name):
self.name = name
self.lock = None
def __enter__(self):
self.lock = _get_lock(self.name)
self.lock.acquire()
#logger.debug('%s got lock %s' % (threading.current_thread().name, self.name))
def __exit__(self, type, value, traceback):
self.lock.release()
#logger.debug('%s released lock %s' % (threading.current_thread().name, self.name))
def lock(name='defaultLock'):
def wrap(f):
@functools.wraps(f)
def inner(*args, **kwargs):
with NamedLock(name):
retval = f(*args, **kwargs)
return retval
return inner
return wrap
class Request(object):
def __init__(self):
self.headers = None
@ -80,28 +121,28 @@ class Daemon(object):
A generic daemon class.
Usage: subclass the Daemon class and override the run() method
"""
atexit_hooks = []
"""
atexit_hooks = []
def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = pidfile
@staticmethod
def register_atexit_hook(hook):
Daemon.atexit_hooks.append(hook)
@staticmethod
def _atexit():
for hook in Daemon.atexit_hooks:
try:
def register_atexit_hook(hook):
Daemon.atexit_hooks.append(hook)
@staticmethod
def _atexit():
for hook in Daemon.atexit_hooks:
try:
hook()
except Exception:
except Exception:
content = traceback.format_exc()
err = 'Exception when calling atexit hook[%s]\n%s' % (hook.__name__, content)
#logger.error(err)
err = 'Exception when calling atexit hook[%s]\n%s' % (hook.__name__, content)
#logger.error(err)
def daemonize(self):
"""
@ -145,7 +186,7 @@ class Daemon(object):
# write pidfile
Daemon.register_atexit_hook(self.delpid)
atexit.register(Daemon._atexit)
atexit.register(Daemon._atexit)
pid = str(os.getpid())
file(self.pidfile,'w').write("%s\n" % pid)
@ -173,12 +214,12 @@ class Daemon(object):
sys.exit(0)
# Start the daemon
self.daemonize()
self.daemonize()
try:
self.run()
except Exception:
content = traceback.format_exc()
#logger.error(content)
self.run()
except Exception:
content = traceback.format_exc()
#logger.error(content)
sys.exit(1)
def stop(self):
@ -192,25 +233,29 @@ class Daemon(object):
pf.close()
except IOError:
pid = None
if not pid:
message = "pidfile %s does not exist. Daemon not running?\n"
sys.stderr.write(message % self.pidfile)
return # not an error in a restart
# Try killing the daemon process
try:
while 1:
os.kill(pid, SIGTERM)
time.sleep(0.1)
except OSError, err:
err = str(err)
if err.find("No such process") > 0:
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
wait_stop = 5
start_time = time.time()
while 1:
if os.path.exists('/proc/' + str(pid)):
curr_time = time.time()
if (curr_time - start_time) > wait_stop:
os.kill(pid, SIGKILL)
else:
os.kill(pid, SIGTERM)
time.sleep(0.3)
else:
print str(err)
sys.exit(1)
if os.path.exists(self.pidfile):
self.delpid()
break
print "Stop Daemon Successfully"
def restart(self):
"""

View File

@ -29,35 +29,12 @@ import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import com.cloud.agent.api.*;
import com.cloud.utils.Pair;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.log4j.Logger;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CheckNetworkAnswer;
import com.cloud.agent.api.CheckNetworkCommand;
import com.cloud.agent.api.CheckVirtualMachineAnswer;
import com.cloud.agent.api.CheckVirtualMachineCommand;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.MaintainAnswer;
import com.cloud.agent.api.MaintainCommand;
import com.cloud.agent.api.MigrateAnswer;
import com.cloud.agent.api.MigrateCommand;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.PrepareForMigrationAnswer;
import com.cloud.agent.api.PrepareForMigrationCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.RebootAnswer;
import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.SecurityGroupRulesCmd;
import com.cloud.agent.api.StartAnswer;
import com.cloud.agent.api.StartCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.api.StopCommand;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand.BootDev;
import com.cloud.agent.api.baremetal.IpmiBootorResetCommand;
@ -373,7 +350,21 @@ public class BareMetalResourceBase extends ManagerBase implements ServerResource
return null;
}
return new PingRoutingCommand(getType(), id, deltaSync());
if (hostId != null) {
vmDao = ComponentContext.getComponent(VMInstanceDao.class);
final List<? extends VMInstanceVO> vms = vmDao.listByHostId(hostId);
if (vms.isEmpty()) {
return new PingRoutingCommand(getType(), id, deltaSync());
} else {
VMInstanceVO vm = vms.get(0);
SecurityGroupHttpClient client = new SecurityGroupHttpClient();
HashMap<String, Pair<Long, Long>> nwGrpStates = client.sync(vm.getInstanceName(), vm.getId(), vm.getPrivateIpAddress());
return new PingRoutingWithNwGroupsCommand(getType(), id, null, nwGrpStates);
}
} else {
return new PingRoutingCommand(getType(), id, deltaSync());
}
}
protected Answer execute(IpmISetBootDevCommand cmd) {

View File

@ -1,38 +1,221 @@
// 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.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
package com.cloud.baremetal.networkservice;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.SecurityGroupRulesCmd;
public class SecurityGroupHttpClient {
public Answer call(String guestIp, SecurityGroupRulesCmd cmd) {
// TODO Auto-generated method stub
return null;
}
public boolean echo(String ip, long millis, long millis2) {
// TODO Auto-generated method stub
return false;
}
}
// 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.
//
// Automatically generated by addcopyright.py at 01/29/2013
// Apache License, Version 2.0 (the "License"); you may not use this
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.baremetal.networkservice;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.net.SocketTimeoutException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.zip.DeflaterOutputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import com.cloud.agent.api.SecurityGroupRuleAnswer;
import com.cloud.agent.api.SecurityGroupRulesCmd;
import com.cloud.agent.api.SecurityGroupRulesCmd.IpPortAndProto;
import com.cloud.baremetal.networkservice.schema.SecurityGroupRule;
import com.cloud.baremetal.networkservice.schema.SecurityGroupVmRuleSet;
import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.log4j.Logger;
public class SecurityGroupHttpClient {
private static final Logger logger = Logger.getLogger(SecurityGroupHttpClient.class);
private static final String ARG_NAME = "args";
private static final String COMMAND = "command";
private JAXBContext context;
private int port;
private static HttpClient httpClient;
static {
MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManager();
httpClient = new HttpClient(connman);
httpClient.setConnectionTimeout(5000);
}
private enum OpConstant {
setRules, echo,
}
public SecurityGroupHttpClient() {
try {
context = JAXBContext.newInstance(SecurityGroupRule.class, SecurityGroupVmRuleSet.class);
port = 9988;
} catch (Exception e) {
throw new CloudRuntimeException(
"Unable to create JAXBContext for security group", e);
}
}
private List<SecurityGroupRule> generateRules(IpPortAndProto[] ipps) {
List<SecurityGroupRule> rules = new ArrayList<SecurityGroupRule>(
ipps.length);
for (SecurityGroupRulesCmd.IpPortAndProto ipp : ipps) {
SecurityGroupRule r = new SecurityGroupRule();
r.setProtocol(ipp.getProto());
r.setStartPort(ipp.getStartPort());
r.setEndPort(ipp.getEndPort());
for (String cidr : ipp.getAllowedCidrs()) {
r.getIp().add(cidr);
}
rules.add(r);
}
return rules;
}
public HashMap<String, Pair<Long, Long>> sync(String vmName, Long vmId, String agentIp) {
HashMap<String, Pair<Long, Long>> states = new HashMap<String, Pair<Long, Long>>();
PostMethod post = new PostMethod(String.format("http://%s:%s/", agentIp, getPort()));
try {
post.addRequestHeader("command", "sync");
if (httpClient.executeMethod(post) != 200) {
logger.debug(String.format("echoing baremetal security group agent on %s got error: %s", agentIp, post.getResponseBodyAsString()));
} else {
String res = post.getResponseBodyAsString();
// res = ';'.join([vmName, vmId, seqno])
String[] rulelogs = res.split(",");
if (rulelogs.length != 6) {
logger.debug(String.format("host[%s] returns invalid security group sync document[%s], reset rules", agentIp, res));
states.put(vmName, new Pair<Long, Long>(vmId, -1L));
return states;
}
Pair<Long, Long> p = new Pair<Long, Long>(Long.valueOf(rulelogs[1]), Long.valueOf(rulelogs[5]));
states.put(rulelogs[0], p);
return states;
}
} catch (SocketTimeoutException se) {
logger.warn(String.format("unable to sync security group rules on host[%s], %s", agentIp, se.getMessage()));
} catch (Exception e) {
logger.warn(String.format("unable to sync security group rules on host[%s]", agentIp), e);
} finally {
if (post != null) {
post.releaseConnection();
}
}
return states;
}
public boolean echo(String agentIp, long l, long m) {
boolean ret = false;
int count = 1;
while (true) {
try {
Thread.sleep(m);
count++;
} catch (InterruptedException e1) {
logger.warn("", e1);
break;
}
PostMethod post = new PostMethod(String.format("http://%s:%s/", agentIp, getPort()));
try {
post.addRequestHeader("command", "echo");
if (httpClient.executeMethod(post) != 200) {
logger.debug(String.format("echoing baremetal security group agent on %s got error: %s", agentIp, post.getResponseBodyAsString()));
} else {
ret = true;
}
break;
} catch (Exception e) {
if (count*m >= l) {
logger.debug(String.format("ping security group agent on vm[%s] timeout after %s minutes, starting vm failed, count=%s", agentIp, TimeUnit.MILLISECONDS.toSeconds(l), count));
break;
} else {
logger.debug(String.format("Having pinged security group agent on vm[%s] %s times, continue to wait...", agentIp, count));
}
} finally {
if (post != null) {
post.releaseConnection();
}
}
}
return ret;
}
public SecurityGroupRuleAnswer call(String agentIp,
SecurityGroupRulesCmd cmd) {
PostMethod post = new PostMethod(String.format(
"http://%s:%s", agentIp, getPort()));
try {
SecurityGroupVmRuleSet rset = new SecurityGroupVmRuleSet();
rset.getEgressRules().addAll(generateRules(cmd.getEgressRuleSet()));
rset.getIngressRules().addAll(
generateRules(cmd.getIngressRuleSet()));
rset.setVmName(cmd.getVmName());
rset.setVmIp(cmd.getGuestIp());
rset.setVmMac(cmd.getGuestMac());
rset.setVmId(cmd.getVmId());
rset.setSignature(cmd.getSignature());
rset.setSequenceNumber(cmd.getSeqNum());
Marshaller marshaller = context.createMarshaller();
StringWriter writer = new StringWriter();
marshaller.marshal(rset, writer);
String xmlContents = writer.toString();
logger.debug(xmlContents);
post.addRequestHeader("command", "set_rules");
StringRequestEntity entity = new StringRequestEntity(xmlContents);
post.setRequestEntity(entity);
if (httpClient.executeMethod(post) != 200) {
return new SecurityGroupRuleAnswer(cmd, false,
post.getResponseBodyAsString());
} else {
return new SecurityGroupRuleAnswer(cmd);
}
} catch (Exception e) {
return new SecurityGroupRuleAnswer(cmd, false, e.getMessage());
} finally {
if (post != null) {
post.releaseConnection();
}
}
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}

View File

@ -0,0 +1,55 @@
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2012.07.11 at 03:24:15 PM PDT
//
package com.cloud.baremetal.networkservice.schema;
import javax.xml.bind.annotation.XmlRegistry;
/**
* This object contains factory methods for each
* Java content interface and Java element interface
* generated in the com.cloud.network.security.schema package.
* <p>An ObjectFactory allows you to programatically
* construct new instances of the Java representation
* for XML content. The Java representation of XML
* content can consist of schema derived interfaces
* and classes representing the binding of schema
* type definitions, element declarations and model
* groups. Factory methods for each of these are
* provided in this class.
*
*/
@XmlRegistry
public class ObjectFactory {
/**
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.cloud.network.security.schema
*
*/
public ObjectFactory() {
}
/**
* Create an instance of {@link SecurityGroupRule }
*
*/
public SecurityGroupRule createSecurityGroupRule() {
return new SecurityGroupRule();
}
/**
* Create an instance of {@link SecurityGroupVmRuleSet }
*
*/
public SecurityGroupVmRuleSet createSecurityGroupVmRuleSet() {
return new SecurityGroupVmRuleSet();
}
}

View File

@ -0,0 +1,146 @@
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2012.07.11 at 03:24:15 PM PDT
//
package com.cloud.baremetal.networkservice.schema;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for SecurityGroupRule complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* &lt;complexType name="SecurityGroupRule">
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element name="protocol" type="{http://www.w3.org/2001/XMLSchema}string"/>
* &lt;element name="startPort" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
* &lt;element name="endPort" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
* &lt;sequence maxOccurs="unbounded" minOccurs="0">
* &lt;element name="ip" type="{http://www.w3.org/2001/XMLSchema}string"/>
* &lt;/sequence>
* &lt;/sequence>
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "SecurityGroupRule", propOrder = {
"protocol",
"startPort",
"endPort",
"ip"
})
public class SecurityGroupRule {
@XmlElement(required = true)
protected String protocol;
@XmlSchemaType(name = "unsignedInt")
protected long startPort;
@XmlSchemaType(name = "unsignedInt")
protected long endPort;
protected List<String> ip;
/**
* Gets the value of the protocol property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getProtocol() {
return protocol;
}
/**
* Sets the value of the protocol property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setProtocol(String value) {
this.protocol = value;
}
/**
* Gets the value of the startPort property.
*
*/
public long getStartPort() {
return startPort;
}
/**
* Sets the value of the startPort property.
*
*/
public void setStartPort(long value) {
this.startPort = value;
}
/**
* Gets the value of the endPort property.
*
*/
public long getEndPort() {
return endPort;
}
/**
* Sets the value of the endPort property.
*
*/
public void setEndPort(long value) {
this.endPort = value;
}
/**
* Gets the value of the ip property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the ip property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getIp().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link String }
*
*
*/
public List<String> getIp() {
if (ip == null) {
ip = new ArrayList<String>();
}
return this.ip;
}
}

View File

@ -0,0 +1,263 @@
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2012.07.11 at 03:24:15 PM PDT
//
package com.cloud.baremetal.networkservice.schema;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* &lt;complexType>
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element name="vmName" type="{http://www.w3.org/2001/XMLSchema}string"/>
* &lt;element name="vmId" type="{http://www.w3.org/2001/XMLSchema}long"/>
* &lt;element name="vmIp" type="{http://www.w3.org/2001/XMLSchema}string"/>
* &lt;element name="vmMac" type="{http://www.w3.org/2001/XMLSchema}string"/>
* &lt;element name="signature" type="{http://www.w3.org/2001/XMLSchema}string"/>
* &lt;element name="sequenceNumber" type="{http://www.w3.org/2001/XMLSchema}long"/>
* &lt;sequence maxOccurs="unbounded" minOccurs="0">
* &lt;element name="ingressRules" type="{}SecurityGroupRule"/>
* &lt;/sequence>
* &lt;sequence maxOccurs="unbounded" minOccurs="0">
* &lt;element name="egressRules" type="{}SecurityGroupRule"/>
* &lt;/sequence>
* &lt;/sequence>
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"vmName",
"vmId",
"vmIp",
"vmMac",
"signature",
"sequenceNumber",
"ingressRules",
"egressRules"
})
@XmlRootElement(name = "SecurityGroupVmRuleSet")
public class SecurityGroupVmRuleSet {
@XmlElement(required = true)
protected String vmName;
protected long vmId;
@XmlElement(required = true)
protected String vmIp;
@XmlElement(required = true)
protected String vmMac;
@XmlElement(required = true)
protected String signature;
protected long sequenceNumber;
protected List<SecurityGroupRule> ingressRules;
protected List<SecurityGroupRule> egressRules;
/**
* Gets the value of the vmName property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getVmName() {
return vmName;
}
/**
* Sets the value of the vmName property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setVmName(String value) {
this.vmName = value;
}
/**
* Gets the value of the vmId property.
*
*/
public long getVmId() {
return vmId;
}
/**
* Sets the value of the vmId property.
*
*/
public void setVmId(long value) {
this.vmId = value;
}
/**
* Gets the value of the vmIp property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getVmIp() {
return vmIp;
}
/**
* Sets the value of the vmIp property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setVmIp(String value) {
this.vmIp = value;
}
/**
* Gets the value of the vmMac property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getVmMac() {
return vmMac;
}
/**
* Sets the value of the vmMac property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setVmMac(String value) {
this.vmMac = value;
}
/**
* Gets the value of the signature property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getSignature() {
return signature;
}
/**
* Sets the value of the signature property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setSignature(String value) {
this.signature = value;
}
/**
* Gets the value of the sequenceNumber property.
*
*/
public long getSequenceNumber() {
return sequenceNumber;
}
/**
* Sets the value of the sequenceNumber property.
*
*/
public void setSequenceNumber(long value) {
this.sequenceNumber = value;
}
/**
* Gets the value of the ingressRules property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the ingressRules property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getIngressRules().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link SecurityGroupRule }
*
*
*/
public List<SecurityGroupRule> getIngressRules() {
if (ingressRules == null) {
ingressRules = new ArrayList<SecurityGroupRule>();
}
return this.ingressRules;
}
/**
* Gets the value of the egressRules property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the egressRules property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getEgressRules().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link SecurityGroupRule }
*
*
*/
public List<SecurityGroupRule> getEgressRules() {
if (egressRules == null) {
egressRules = new ArrayList<SecurityGroupRule>();
}
return this.egressRules;
}
}

View File

@ -510,7 +510,9 @@
</properties>
<modules>
<module>developer</module>
<!--
<module>tools</module>
-->
</modules>
</profile>
<profile>