예제 #1
0
    def generate(self):
        LOG.info('%s()' % KenLog.fcn())

        self._action = KenLog.fcn()
        cloud_internal = CloudModel.internal(self._models['CloudModel'])

        control_planes = CloudModel.get(cloud_internal, 'control-planes', {})
        # If we have an error in an earlier generator we may not have
        # control_planes in the internal model
        if not control_planes:
            return

        routes = {}
        for cp_name, cp in control_planes.iteritems():

            load_balancers = cp.get('load-balancer-config', {})

            for cluster in cp['clusters']:
                for server in cluster.get('servers', []):
                    self._add_routes_from_server(cp, server, load_balancers, routes)

            for r_name, r in cp.get('resources', {}).iteritems():
                for server in r.get('servers', []):
                    self._add_routes_from_server(cp, server, load_balancers, routes)

        #
        default_routes = {}
        # Warn about any routes using the "default" route
        for src_net, net_routes in routes.iteritems():
            for dest_net, route_data in net_routes.iteritems():
                if route_data['default']:
                    hosts = set()
                    if src_net not in default_routes:
                        default_routes[src_net] = []
                    for src, src_data in route_data['used_by'].iteritems():
                        for dest, host_list in src_data.iteritems():
                            for host in host_list:
                                hosts.add(host)
                    default_routes[src_net].append({'net': dest_net, 'hosts': hosts})

        if default_routes:
            msg = ("Default routing used between networks\n"
                   "The following networks are using a 'default' route rule. To remove this warning\n"
                   "either add an explicit route in the source network group or force the network to\n"
                   "attach in the interface model used by the servers.\n")
            for src in sorted(default_routes):
                dest_list = default_routes[src]
                for dest_data in dest_list:
                    msg += "  %s to %s\n" % (src, dest_data['net'])
                    for host in sorted(dest_data['hosts']):
                        msg += "    %s\n" % (host)
            self.add_warning(msg)

        CloudModel.put(cloud_internal, 'routes', routes)
 def _generate_ring_specifications_info(self):
     LOG.info('%s()' % KenLog.fcn())
     self._action = KenLog.fcn()
     cloud_version = CloudModel.version(
         self._models['CloudModel'], self._version)
     ring_specifications_config = CloudModel.get(
         cloud_version, 'ring-specifications', [])
     cloud_internal = CloudModel.internal(self._models['CloudModel'])
     CloudModel.put(cloud_internal,
                    'ring-specifications',
                    ring_specifications_config)
    def generate(self):
        LOG.info('%s()' % KenLog.fcn())
        self._action = KenLog.fcn()
        cloud_version = CloudModel.version(self._models['CloudModel'],
                                           self._version)
        cloud_internal = CloudModel.internal(self._models['CloudModel'])

        networks = {}
        network_groups = {}

        for group in CloudModel.get(cloud_version, 'network-groups'):
            network_groups[group['name']] = group
            network_groups[group['name']]['networks'] = []

        for net in CloudModel.get(cloud_version, 'networks'):
            networks[net['name']] = net

        # add networks into their respective network groups
        for net_name, net in networks.iteritems():
            if net.get('network-group', None):
                network_groups[net['network-group']]['networks'].append(net)

        # Inject a network group for each provider network, so we can support
        # routes to them
        for config_data in CloudModel.get(cloud_version, 'configuration-data',
                                          []):
            if 'neutron' in config_data.get('services', []):
                for net in config_data.get('data',
                                           {}).get('neutron_provider_networks',
                                                   []):
                    provider_net = {
                        'name': net['name'],
                        'cidr': net['cidr'],
                        'network-group': net['name'],
                        'neutron_network': True
                    }
                    group = {'name': net['name'], 'networks': [provider_net]}
                    networks[net['name']] = provider_net
                    network_groups[net['name']] = group

        self._generate_default_network_mtu(network_groups)

        CloudModel.put(cloud_internal, 'networks', networks)
        CloudModel.put(cloud_internal, 'network-groups', network_groups)
예제 #4
0
    def generate(self):
        LOG.info('%s()' % KenLog.fcn())

        cloud_internal = CloudModel.internal(self._models['CloudModel'])
        control_planes = CloudModel.get(cloud_internal, 'control-planes', [])

        for cp_name, cp in control_planes.iteritems():
            deleted_components = []
            for cluster in cp['clusters']:
                for server in cluster['servers']:
                    self._add_deleted_components(deleted_components, server)

            for r_name, resources in cp.get('resources', {}).iteritems():
                for server in resources.get('servers', []):
                    self._add_deleted_components(deleted_components, server)

            cp['deleted-components'] = deleted_components

        CloudModel.put(cloud_internal, 'control-planes', control_planes)
예제 #5
0
    def generate(self):
        LOG.info('%s()' % KenLog.fcn())

        self._action = KenLog.fcn()
        cloud_internal = CloudModel.internal(self._models['CloudModel'])

        control_planes = CloudModel.get(cloud_internal, 'control-planes')
        networks = CloudModel.get(cloud_internal, 'networks')
        network_groups = CloudModel.get(cloud_internal, 'network-groups')
        components = CloudModel.get(cloud_internal, 'components')

        cp_topology = self._generate_cp_topology(control_planes, components)
        CloudModel.put(cloud_internal, 'cp-topology', cp_topology)

        CloudModel.put(cloud_internal, 'region-topology',
                       self._generate_region_topology(control_planes))

        CloudModel.put(cloud_internal, 'service-topology',
                       self._generate_service_topology(cp_topology))

        CloudModel.put(
            cloud_internal, 'network-topology',
            self._generate_network_topology(network_groups, networks,
                                            control_planes))
    def generate(self):
        LOG.info('%s()' % KenLog.fcn())

        cloud_data = self._models['CloudDescription']['cloud']
        cloud_version = CloudModel.version(self._models['CloudModel'],
                                           self._version)
        cloud_internal = CloudModel.internal(self._models['CloudModel'])

        services = {}
        components = {}
        components_by_mnemonic = {}

        for service in CloudModel.get(cloud_version, 'services'):
            services[service['name']] = service

        for component in CloudModel.get(cloud_version, 'service-components'):
            components[component['name']] = component
            components_by_mnemonic[component['mnemonic']] = component

        control_planes = {}
        iface_models = {}
        disk_models = {}
        nic_mappings = {}
        nic_device_types = {}
        nic_device_families = {}
        server_roles = {}
        server_groups = {}
        bm_servers = []
        pass_through = {'global': {}, 'servers': {}}

        # Servers
        if 'servers' in cloud_version:
            bm_servers.extend(cloud_version['servers'])

        # Build a list of server addresses so we can
        # reserve them
        server_addresses = {}
        for s in bm_servers:
            server_addresses[s['ip-addr']] = s['id']

        # Control Planes
        for cp in CloudModel.get(cloud_version, 'control-planes'):
            control_planes[cp['name']] = dict(cp)

        # Network Groups
        network_groups = CloudModel.get(cloud_internal, 'network-groups')

        # Networks
        networks = CloudModel.get(cloud_internal, 'networks')

        # Interface Models
        for iface in CloudModel.get(cloud_version, 'interface-models'):
            iface_models[iface['name']] = iface

        # Disk Models
        for disk_model in CloudModel.get(cloud_version, 'disk-models'):
            disk_models[disk_model['name']] = disk_model

        # NIC Device Families
        for nic_family in CloudModel.get(cloud_version, 'nic-device-families',
                                         []):
            nic_device_families[nic_family['name']] = nic_family

        # NIC Device Types
        for nic_dev in CloudModel.get(cloud_version, 'nic-device-types', []):
            nic_device_types[nic_dev['name']] = nic_dev
            nic_device_types[nic_dev['name']]['family_data'] = \
                nic_device_families[nic_dev['family']]

        # NIC Mapping
        for nic_map in CloudModel.get(cloud_version, 'nic-mappings', []):
            for port in nic_map.get('physical-ports', []):
                # Add in any data from the NIC device type
                if 'nic-device-type' in port:
                    port['nic-device-type'] = nic_device_types[
                        port['nic-device-type']]
            nic_mappings[nic_map['name']] = nic_map

        # Server Roles
        for role in CloudModel.get(cloud_version, 'server-roles'):
            server_roles[role['name']] = role

        # Server Groups
        for group in CloudModel.get(cloud_version, 'server-groups', []):
            server_groups[group['name']] = group

        # Pass Through
        pt_data = CloudModel.get(cloud_version, 'pass-through', [])

        ####################################
        #
        # End of reading input data
        #
        ###################################

        # Combine pass through data which maybe in multiple
        # input files into a single dict structured by server and
        # control plane.
        for pt in pt_data:
            for key in pt.get('global', {}):
                if key in pass_through['global']:
                    msg = ("Key %s is defined more than once in global "
                           "pass-through data" % (key, ))
                    self.add_error(msg)

                pass_through['global'][key] = pt['global'][key]

            for server in pt.get('servers', []):
                if server['id'] not in pass_through['servers']:
                    pass_through['servers'][server['id']] = {}
                server_data = pass_through['servers'][server['id']]

                for key in server.get('data'):
                    if key in server_data:
                        msg = (
                            "Key %s is defined more than once for server %s "
                            "in pass-through data" % (key, server['id']))
                        self.add_error(msg)
                    server_data[key] = server['data'][key]

        # Add proxy relationships
        for component_name, component in components.iteritems():
            for container_data in component.get('has-container', []):
                container_name = container_data['service-name']
                if container_name in components_by_mnemonic:
                    container_name = components_by_mnemonic[container_name][
                        'name']
                if 'contains' not in components[container_name]:
                    components[container_name]['contains'] = {}
                components[container_name]['contains'][component_name] = {
                    'name': component['mnemonic'].replace('-', '_'),
                    'data': container_data
                }
                component['container-name'] = container_name

        # Can't do any more if we have errors in the network groups
        if self._errors:
            return

        # Create a default interface-model for any roles that don't define one
        default_net_iface = [{
            'name': 'default_iface',
            'network-groups': [x for x in network_groups],
            'ports': ['ethX']
        }]

        # Create a deafult server group to hold any networks and servers not
        # specificially assigned
        default_server_group = {}

        # Fix up relationships between server groups
        for group_name, group in server_groups.iteritems():
            for child in ServerGroup.server_groups(group):
                ServerGroup.add_group(group, server_groups[child])

        # Map networks to net_groups in server groups
        networks_in_a_group = set()
        for group_name, group in server_groups.iteritems():
            for net in ServerGroup.networks(group):
                ServerGroup.add_network(group, net,
                                        networks[net]['network-group'])
                networks_in_a_group.add(net)

        # Add any unassinged networks to the default server group
        for net_name, net in networks.iteritems():
            if net_name not in networks_in_a_group and not net.get(
                    'neutron_network', False):
                if server_groups:
                    self.add_warning("Network %s is not listed in a server "
                                     "group." % (net_name))
                ServerGroup.add_network(default_server_group, net_name,
                                        net['network-group'])

        # Establish the min and max size of each cluster and resource group
        for cp_name, cp in control_planes.iteritems():
            for cluster in cp.get('clusters', []):
                if 'member-count' in cluster:
                    cluster['min-count'] = cluster['member-count']
                    cluster['max-count'] = cluster['member-count']
                else:
                    cluster['min-count'] = cluster.get('min-count', 1)

            for rgroup in cp.get('resources', []):
                if 'member-count' in rgroup:
                    rgroup['min-count'] = rgroup['member-count']
                    rgroup['max-count'] = rgroup['member-count']
                else:
                    rgroup['min-count'] = rgroup.get('min-count', 0)

        # Create a list of servers with the network details for each resolved
        servers = []
        for s in bm_servers:

            server_role = server_roles[s['role']]

            # resolve the networking

            # Find the interface model, and take a copy of the interfaces, as we may only use part of the model
            # If there is no interface-model in the server role then all networks map to the existing NIC
            fcoe_interfaces = []
            if 'interface-model' in server_role:
                iface_model = iface_models[server_role['interface-model']]
                server_interfaces = deepcopy(iface_model['network-interfaces'])
                if 'fcoe-interfaces' in iface_model:
                    fcoe_interfaces = iface_model['fcoe-interfaces']
            else:
                server_interfaces = deepcopy(default_net_iface)

            # Find the disk model, and take a copy
            if 'disk-model' in server_role:
                disk_model = deepcopy(disk_models[server_role['disk-model']])
            else:
                disk_model = {'drives': {}}

            # Translate network groups to the specific networks for this server
            # Note:  At this stage we have all possible networks groups defined
            #        by the interface model.  We will reduce that to just those
            #        needed once we have assinged the server to a particular role
            for iface in server_interfaces:
                iface['networks'] = {}
                iface_net_groups = (
                    iface.get('network-groups', []) +
                    iface.get('forced-network-groups', []) +
                    iface.get('passthrough-network-groups', []))
                for net_group in iface_net_groups:
                    # Find network in the group for this server
                    if 'server-group' in s:
                        server_group = server_groups[s['server-group']]
                    else:
                        server_group = None
                    net_name = ServerGroup.find_network(
                        server_group, net_group, default_server_group)
                    if net_name:
                        network = networks[net_name]
                        iface['networks'][network['name']] = deepcopy(network)
                        if net_group in iface.get('forced-network-groups', []):
                            iface['networks'][network['name']]['forced'] = True
                        else:
                            iface['networks'][
                                network['name']]['forced'] = False

                        # Marked the network as passthrough if its network group is
                        # in the list of passthought network groups.
                        if net_group not in iface.get(
                                'passthrough-network-groups', []):
                            iface['networks'][
                                network['name']]['passthrough'] = False
                            iface['networks'][
                                network['name']]['passthrough-only'] = False
                        else:
                            iface['networks'][
                                network['name']]['passthrough'] = True

                            # Mark the network as passthrough-only if its network group is
                            # not listed in network-groups or forced-network-groups
                            if net_group not in (
                                    iface.get('network-groups', []) +
                                    iface.get('forced-network-groups', [])):
                                iface['networks'][
                                    network['name']]['passthrough-only'] = True
                            else:
                                iface['networks'][network['name']][
                                    'passthrough-only'] = False

            server = {
                'id': s['id'],
                'hostname': s.get('hostname', None),
                'hypervisor-id': s.get('hypervisor-id', None),
                'role': s['role'],
                'server_group': s.get('server-group'),
                'rack': s.get('rack'),
                'addr': s['ip-addr'],
                'if-model': server_role.get('interface-model', 'default'),
                'disk-model': disk_model,
                'interfaces': server_interfaces,
                'fcoe_interfaces': fcoe_interfaces,
                'nic_map': nic_mappings.get(s.get('nic-mapping', 'none')),
                'ansible_options': s.get('ansible-options'),
                'state': None,
                'vm-factory': s.get('vm-factory', False),
                'port-groups': s.get('port-groups', []),
                'previous_config': {}
            }

            servers.append(server)

            # Add servers to ServerGroups
            if 'server-group' in s:
                sgrp = server_groups[s['server-group']]
                ServerGroup.add_server(sgrp, server)
                server['server-group-list'] = ServerGroup.get_group_list(sgrp)
            else:
                # If there are server groups defined it would be odd to have
                # a server which isn't a member of a group
                if server_groups:
                    self.add_warning("Server %s is not a member of a server "
                                     "group." % (s['ip-addr']))
                ServerGroup.add_server(default_server_group, server)
                server['server-group-list'] = []

        # Roles for a cluster/resource can be either a string or a list, so change to
        # always be a list
        for cp_name, cp in control_planes.iteritems():
            for cluster in cp['clusters']:
                if isinstance(cluster['server-role'], basestring):
                    cluster['server-role'] = [cluster['server-role']]

            for r in cp.get('resources', []):
                if isinstance(r['server-role'], basestring):
                    r['server-role'] = [r['server-role']]

        # Add a list of all services to each Control Plane
        for cp_name, cp in control_planes.iteritems():
            cp['services'] = {}
            for cluster in cp['clusters']:
                cluster['services'] = {}
                for comp_name in cluster['service-components']:
                    service_name = components[comp_name]['service']
                    if service_name not in cluster['services']:
                        cluster['services'][service_name] = []
                    cluster['services'][service_name].append(comp_name)
                    cp['services'][service_name] = {}

            for r in cp.get('resources', []):
                r['services'] = {}
                for comp_name in r['service-components']:
                    service_name = components[comp_name]['service']
                    if service_name not in r['services']:
                        r['services'][service_name] = []
                    r['services'][service_name].append(comp_name)
                    cp['services'][service_name] = {}

        ntp_servers = cloud_data.get('ntp-servers', [])
        dns_settings = cloud_data.get('dns-settings', {})
        smtp_settings = cloud_data.get('smtp-settings', {})
        firewall_settings = cloud_data.get('firewall-settings', {})

        CloudModel.put(cloud_internal, 'control-planes', control_planes)
        CloudModel.put(cloud_internal, 'networks', networks)
        CloudModel.put(cloud_internal, 'servers', servers)
        CloudModel.put(cloud_internal, 'server-groups', server_groups)
        CloudModel.put(cloud_internal, 'default-server-group',
                       default_server_group)
        CloudModel.put(cloud_internal, 'services', services)
        CloudModel.put(cloud_internal, 'components', components)
        CloudModel.put(cloud_internal, 'components_by_mnemonic',
                       components_by_mnemonic)
        CloudModel.put(cloud_internal, 'ntp_servers', ntp_servers)
        CloudModel.put(cloud_internal, 'dns_settings', dns_settings)
        CloudModel.put(cloud_internal, 'smtp_settings', smtp_settings)
        CloudModel.put(cloud_internal, 'firewall_settings', firewall_settings)
        CloudModel.put(cloud_internal, 'pass_through', pass_through)
        CloudModel.put(cloud_internal, 'iface_models', iface_models)
        CloudModel.put(cloud_internal, 'disk_models', disk_models)
        CloudModel.put(cloud_internal, 'nic_mappings', nic_mappings)
        CloudModel.put(cloud_internal, 'server_roles', server_roles)
    def _generate_firewall_rules(self):
        LOG.info('%s()' % KenLog.fcn())
        self._action = KenLog.fcn()
        cloud_version = CloudModel.version(self._models['CloudModel'],
                                           self._version)
        cloud_internal = CloudModel.internal(self._models['CloudModel'])

        firewall_rules = CloudModel.get(cloud_version, 'firewall-rules', [])
        network_groups = CloudModel.get(cloud_version, 'network-groups')
        components = CloudModel.get(cloud_internal, 'components', [])

        # If component is not set then it means an earlier generator failed
        if not components:
            return

        # Initialise the firewall structure
        net_group_firewall = {}
        for net_group in network_groups:
            net_group_firewall[net_group['name']] = {
                'user': [],
                'component': {}
            }

        #
        # Add ports from components.
        #
        explicit_components = set()
        for net_group in network_groups:
            for comp in self._get_netgroup_components(net_group,
                                                      exclude_default=True):
                explicit_components.add(comp)

        for net_group in network_groups:
            net_group_components = self._get_netgroup_components(net_group)
            for comp_name, comp_data in components.iteritems():
                if (comp_name in net_group_components
                        or ('default' in net_group_components
                            and comp_name not in explicit_components)):
                    comp_rules = []
                    for endpoint in comp_data.get('endpoints', []):

                        if (comp_name in net_group.get(
                                'tls-component-endpoints', [])
                                or 'default' in net_group.get(
                                    'tls-component-endpoints', [])):
                            port_str = endpoint.get('tls-port',
                                                    endpoint['port'])
                        else:
                            port_str = endpoint['port']

                        if ':' in str(port_str):
                            ports = str.split(port_str, ':')
                        else:
                            ports = [port_str, port_str]

                        rule = {
                            'type': 'allow',
                            'remote-ip-prefix': '0.0.0.0/0',
                            'port-range-min': ports[0],
                            'port-range-max': ports[1],
                            'protocol': endpoint.get('protocol', 'tcp')
                        }

                        comp_rules.append(rule)

                    if comp_rules:
                        net_group_firewall[net_group['name']]['component'][
                            comp_name] = comp_rules

        # Annotate the rules so we can trace where they came from
        for rule_group in firewall_rules:
            for rule in rule_group.get('rules', []):
                rule['component'] = "user-%s" % rule_group['name']

        #
        # Add user defined rules to network groups
        #
        for rule in firewall_rules:
            if rule.get('final'):
                continue
            for firewall_netgroup in rule['network-groups']:
                for net_group in network_groups:
                    if (firewall_netgroup == "all"
                            or firewall_netgroup == net_group['name']):
                        net_group_firewall[net_group['name']]['user'].extend(
                            rule['rules'])

        #
        # Add user defined final rules to network groups
        #
        for rule in firewall_rules:
            if not rule.get('final'):
                continue
            for firewall_netgroup in rule['network-groups']:
                for net_group in network_groups:
                    if (firewall_netgroup == "all"
                            or firewall_netgroup == net_group['name']):
                        net_group_firewall[net_group['name']]['user'].extend(
                            rule['rules'])

        CloudModel.put(cloud_internal, 'net-group-firewall',
                       net_group_firewall)