Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 2nd, 2012  |  syntax: None  |  size: 6.55 KB  |  hits: 12  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #!/usr/bin/env python
  2. # pylint: disable-msg=C0103
  3. # vim: tabstop=4 shiftwidth=4 softtabstop=4
  4.  
  5. # Copyright 2010 United States Government as represented by the
  6. # Administrator of the National Aeronautics and Space Administration.
  7. # All Rights Reserved.
  8. #
  9. #    Licensed under the Apache License, Version 2.0 (the "License");
  10. #    you may not use this file except in compliance with the License.
  11. #    You may obtain a copy of the License at
  12. #
  13. #        http://www.apache.org/licenses/LICENSE-2.0
  14. #
  15. #    Unless required by applicable law or agreed to in writing, software
  16. #    distributed under the License is distributed on an "AS IS" BASIS,
  17. #    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. #    See the License for the specific language governing permissions and
  19. #    limitations under the License.
  20.  
  21. import gettext
  22. import os
  23. import sys
  24. import time
  25.  
  26. # If ../nova/__init__.py exists, add ../ to Python search path, so that
  27. # it will override what happens to be installed in /usr/(local/)lib/python...
  28. possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
  29.                                    os.pardir,
  30.                                    os.pardir))
  31. if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
  32.     sys.path.insert(0, possible_topdir)
  33.  
  34. gettext.install('nova', unicode=1)
  35.  
  36. from nova.auth import manager
  37. from nova import context
  38. from nova import db
  39. from nova import exception
  40. from nova import flags
  41. from nova import log as logging
  42. from nova import rpc
  43. from nova import utils
  44. from nova.db.sqlalchemy import session
  45. from nova.db.sqlalchemy import models
  46.  
  47.  
  48. FLAGS = flags.FLAGS
  49. LOG = logging.getLogger('nova-allow')
  50.  
  51.  
  52. admin = context.get_admin_context()
  53.  
  54.  
  55. def set_engine(conn_string):
  56.     if FLAGS.sql_connection != conn_string:
  57.         session._ENGINE = None
  58.         session._MAKER = None
  59.         FLAGS.sql_connection = conn_string
  60.  
  61.  
  62. def get_networks(last_check=0):
  63.     set_engine(FLAGS.sql_connection)
  64.     sess = session.get_session()
  65.     return sess.query(models.Network).filter_by(deleted=False).all()
  66.  
  67.  
  68.  
  69. def add_rules_for(project_id, cidr):
  70.     LOG.info("Checking add for project %s / %s", project_id, cidr)
  71.  
  72.     ensure_default_security_groups(admin, project_id)
  73.     security_group = db.security_group_get_by_name(admin,
  74.                                                    project_id,
  75.                                                    'default')
  76.  
  77.     def add_rule(rule):
  78.         if not security_group_rule_exists(security_group, rule):
  79.             LOG.info("Adding rule %s: %s", rule['protocol'], rule)
  80.             db.security_group_rule_create(admin, rule)
  81.  
  82.             return True
  83.         return False
  84.     did_update = (
  85.         add_rule({'cidr': cidr,
  86.                   'user_id': 'admin',
  87.                   'from_port': 0,
  88.                   'to_port': 65535,
  89.                   'protocol': 'tcp',
  90.                   'parent_group_id': security_group['id']}) or
  91.         add_rule({'cidr': cidr,
  92.                   'user_id': 'admin',
  93.                   'from_port': 0,
  94.                   'to_port': 65535,
  95.                   'protocol': 'udp',
  96.                   'parent_group_id': security_group['id']}) or
  97.         add_rule({'cidr': cidr,
  98.                   'user_id': 'admin',
  99.                   'from_port': -1,
  100.                   'to_port': -1,
  101.                   'protocol': 'icmp',
  102.                   'parent_group_id': security_group['id']}))
  103.  
  104.     if did_update:
  105.         update_nodes(security_group)
  106.     else:
  107.         LOG.info("No new rules needed for %s", project_id)
  108.  
  109.  
  110. def ensure_default_security_groups(context, project_id):
  111.     try:
  112.         db.security_group_get_by_name(context,
  113.                                       project_id,
  114.                                       'default')
  115.     except exception.NotFound:
  116.         values = {'name': 'default',
  117.                    'description': 'default',
  118.                    'user_id': 'admin',
  119.                    'project_id': project_id}
  120.         group = db.security_group_create(context, values)
  121.     try:
  122.         db.security_group_get_by_name(context,
  123.                                       project_id,
  124.                                       'default')
  125.     except exception.NotFound:
  126.         values = {'name': 'default',
  127.                    'description': 'default',
  128.                    'user_id': 'admin',
  129.                    'project_id': project_id}
  130.         group = db.security_group_create(context, values)
  131.  
  132.  
  133. def security_group_rule_exists(security_group, values):
  134.     """Indicates whether the specified rule values are already
  135.        defined in the given security group.
  136.     """
  137.     for rule in security_group.rules:
  138.         is_duplicate = True
  139.         for key in ('cidr', 'from_port', 'to_port', 'protocol'):
  140.             if rule[key] != values[key]:
  141.                 is_duplicate = False
  142.                 break
  143.         if is_duplicate:
  144.             return True
  145.     return False
  146.  
  147.  
  148. def update_nodes(security_group):
  149.     nodes = set([instance['host'] for instance in security_group.instances
  150.                  if instance['host'] is not None])
  151.     for node in nodes:
  152.         LOG.info("Triggering update on node %s", node)
  153.         rpc.cast(admin,
  154.                  '%s.%s' % (FLAGS.compute_topic, node),
  155.                  {"method": "refresh_security_group_rules",
  156.                   "args": {"security_group_id": security_group.id}})
  157.  
  158.  
  159. def main():
  160.     # first, make sure every project member has sysadmin and netadmin roles
  161.     auth = manager.AuthManager()
  162.     for project in db.project_get_all(admin):
  163.         if project:
  164.             for member in project.members:
  165.                 roles = db.user_get_roles(admin, member.id)
  166.                 if not auth.has_role(member.id, 'sysadmin'):
  167.                     try:
  168.                         auth.add_role(member.id, 'sysadmin')
  169.                         auth.add_role(member.id, 'sysadmin', project.id)
  170.                     except e:
  171.                         LOG.info("Couldn't add roles for %s, %s",
  172.                                   member.id, project.id)
  173.  
  174.                 if not auth.has_role(member.id, 'netadmin'):
  175.                     try:
  176.                         auth.add_role(member.id, 'netadmin')
  177.                         auth.add_role(member.id, 'netadmin', project.id)
  178.                     except e:
  179.                         LOG.info("Couldn't add roles for %s, %s",
  180.                                   member.id, project.id)
  181.  
  182.     LOG.info("User roles up-to-date")
  183.  
  184.     # next, authorize all ports
  185.     nets = get_networks()
  186.     for net in nets:
  187.         cidr = "0.0.0.0/0"
  188.         add_rules_for(net['project_id'], cidr)
  189.  
  190.  
  191. if __name__ == '__main__':
  192.     utils.default_flagfile('/etc/nova/nova.conf')
  193.     argv = FLAGS(sys.argv)
  194.     logging.setup()
  195.     main()