コード例 #1
0
ファイル: fetcd.py プロジェクト: yarntime/calico
def parse_tier_data(tier, data):
    data = safe_decode_json(data, log_tag="tier %s" % tier)
    try:
        common.validate_tier_data(tier, data)
    except ValidationFailed as e:
        _log.error("Validation failed for tier data for tier %s: %r", tier, e)
        return None
    else:
        return data
コード例 #2
0
ファイル: fetcd.py プロジェクト: ContainerSolutions/calico
def parse_tier_data(tier, data):
    data = safe_decode_json(data, log_tag="tier %s" % tier)
    try:
        common.validate_tier_data(tier, data)
    except ValidationFailed as e:
        _log.error("Validation failed for tier data for tier %s: %r",
                   tier, e)
        return None
    else:
        return data
コード例 #3
0
ファイル: fetcd.py プロジェクト: ContainerSolutions/calico
def parse_ipam_pool(pool_id, raw_json):
    pool = safe_decode_json(raw_json, log_tag="ipam pool %s" % pool_id)
    try:
        common.validate_ipam_pool(pool_id, pool, 4)
    except ValidationFailed as e:
        _log.exception("Validation failed for ipam pool %s: %s; %r",
                       pool_id, pool, e)
        return None
    else:
        return pool
コード例 #4
0
ファイル: fetcd.py プロジェクト: yekeqiang/calico
def parse_rules(profile_id, raw_json):
    rules = safe_decode_json(raw_json, log_tag="rules %s" % profile_id)
    try:
        common.validate_rules(profile_id, rules)
    except ValidationFailed as e:
        _log.exception("Validation failed for profile %s rules: %s; %r",
                       profile_id, rules, e)
        return None
    else:
        return rules
コード例 #5
0
ファイル: fetcd.py プロジェクト: yarntime/calico
def parse_ipam_pool(pool_id, raw_json):
    pool = safe_decode_json(raw_json, log_tag="ipam pool %s" % pool_id)
    try:
        common.validate_ipam_pool(pool_id, pool, 4)
    except ValidationFailed as e:
        _log.exception("Validation failed for ipam pool %s: %s; %r", pool_id,
                       pool, e)
        return None
    else:
        return pool
コード例 #6
0
ファイル: fetcd.py プロジェクト: ContainerSolutions/calico
def parse_profile(profile_id, raw_json, require_selector=False,
                  require_order=False):
    rules = safe_decode_json(raw_json, log_tag="rules %s" % profile_id)
    try:
        common.validate_profile(profile_id, rules)
    except ValidationFailed as e:
        _log.exception("Validation failed for profile %s rules: %s",
                       profile_id, rules)
        return None
    else:
        return rules
コード例 #7
0
ファイル: fetcd.py プロジェクト: ContainerSolutions/calico
def parse_policy(profile_id, raw_json, require_selector=False,
                  require_order=False):
    policy = safe_decode_json(raw_json, log_tag="policy %s" % profile_id)
    try:
        common.validate_policy(profile_id, policy)
    except ValidationFailed as e:
        _log.exception("Validation failed for policy %s: %s",
                       profile_id, policy)
        return None
    else:
        return policy
コード例 #8
0
ファイル: fetcd.py プロジェクト: is00hcw/calico
def parse_policy(profile_id, raw_json, require_selector=False,
                  require_order=False):
    policy = safe_decode_json(raw_json, log_tag="policy %s" % profile_id)
    try:
        common.validate_policy(profile_id, policy)
    except ValidationFailed as e:
        _log.exception("Validation failed for policy %s: %s",
                       profile_id, policy)
        return None
    else:
        return policy
コード例 #9
0
ファイル: fetcd.py プロジェクト: is00hcw/calico
def parse_profile(profile_id, raw_json, require_selector=False,
                  require_order=False):
    rules = safe_decode_json(raw_json, log_tag="rules %s" % profile_id)
    try:
        common.validate_profile(profile_id, rules)
    except ValidationFailed as e:
        _log.exception("Validation failed for profile %s rules: %s",
                       profile_id, rules)
        return None
    else:
        return rules
コード例 #10
0
ファイル: fetcd.py プロジェクト: yarntime/calico
def parse_labels(profile_id, raw_json):
    labels = safe_decode_json(raw_json,
                              log_tag="profile labels for %s" % profile_id)
    try:
        common.validate_labels(profile_id, labels)
    except ValidationFailed:
        _log.exception("Validation failed for profile %s labels : %s",
                       profile_id, labels)
        return None
    else:
        return labels
コード例 #11
0
ファイル: fetcd.py プロジェクト: ContainerSolutions/calico
def parse_labels(profile_id, raw_json):
    labels = safe_decode_json(raw_json,
                              log_tag="profile labels for %s" % profile_id)
    try:
        common.validate_labels(profile_id, labels)
    except ValidationFailed:
        _log.exception("Validation failed for profile %s labels : %s",
                       profile_id, labels)
        return None
    else:
        return labels
コード例 #12
0
ファイル: fetcd.py プロジェクト: yarntime/calico
def parse_tags(profile_id, raw_json):
    tags = safe_decode_json(raw_json, log_tag="tags %s" % profile_id)
    try:
        common.validate_tags(profile_id, tags)
    except ValidationFailed:
        _log.exception("Validation failed for profile %s tags : %s",
                       profile_id, tags)
        return None
    else:
        # The tags aren't in a top-level object so we need to manually
        # intern them here.
        return intern_list(tags)
コード例 #13
0
ファイル: fetcd.py プロジェクト: ContainerSolutions/calico
def parse_endpoint(config, combined_id, raw_json):
    endpoint = safe_decode_json(raw_json,
                                log_tag="endpoint %s" % combined_id.endpoint)
    try:
        common.validate_endpoint(config, combined_id, endpoint)
    except ValidationFailed as e:
        _log.warning("Validation failed for endpoint %s, treating as "
                     "missing: %s; %r", combined_id, e.message, raw_json)
        endpoint = None
    else:
        _log.debug("Validated endpoint : %s", endpoint)
    return endpoint
コード例 #14
0
ファイル: fetcd.py プロジェクト: is00hcw/calico
def parse_host_ep(config, combined_id, raw_json):
    iface_data = safe_decode_json(raw_json,
                                  log_tag="iface %s" % combined_id.endpoint)
    try:
        common.validate_host_endpoint(config, combined_id, iface_data)
    except ValidationFailed as e:
        _log.warning("Validation failed for host endpoint %s, treating as "
                     "missing: %s; %r", combined_id, e.message, raw_json)
        iface_data = None
    else:
        _log.debug("Validated endpoint : %s", iface_data)
    return iface_data
コード例 #15
0
ファイル: fetcd.py プロジェクト: ContainerSolutions/calico
def parse_tags(profile_id, raw_json):
    tags = safe_decode_json(raw_json, log_tag="tags %s" % profile_id)
    try:
        common.validate_tags(profile_id, tags)
    except ValidationFailed:
        _log.exception("Validation failed for profile %s tags : %s",
                       profile_id, tags)
        return None
    else:
        # The tags aren't in a top-level object so we need to manually
        # intern them here.
        return intern_list(tags)
コード例 #16
0
ファイル: fetcd.py プロジェクト: yekeqiang/calico
def parse_endpoint(config, combined_id, raw_json):
    endpoint = safe_decode_json(raw_json,
                                log_tag="endpoint %s" % combined_id.endpoint)
    try:
        common.validate_endpoint(config, combined_id, endpoint)
    except ValidationFailed as e:
        _log.warning("Validation failed for endpoint %s, treating as "
                     "missing: %s; %r", combined_id, e.message, raw_json)
        endpoint = None
    else:
        _log.debug("Validated endpoint : %s", endpoint)
    return endpoint
コード例 #17
0
ファイル: fetcd.py プロジェクト: elfchief/calico
def parse_host_ep(config, combined_id, raw_json):
    iface_data = safe_decode_json(raw_json,
                                  log_tag="iface %s" % combined_id.endpoint)
    try:
        common.validate_host_endpoint(config, combined_id, iface_data)
    except ValidationFailed as e:
        _log.warning("Validation failed for host endpoint %s, treating as "
                     "missing: %s; %r", combined_id, e.message, raw_json)
        iface_data = None
    else:
        _log.debug("Validated endpoint : %s", iface_data)
    return iface_data
コード例 #18
0
    def calculate_new_subnets(self, ports, current_subnets):
        """Calculate and return subnets needed for PORTS.

        Given a current set of PORTS that we need to provide DHCP for,
        calculate all the subnets that we need for those, and get their data
        either from CURRENT_SUBNETS or from reading etcd.

        If the new set of subnets is equivalent to what we already had in
        CURRENT_SUBNETS, return None.  Otherwise return the new set of
        subnets.
        """

        # Gather required subnet IDs.
        subnet_ids = set()
        for port in ports:
            for fixed_ip in port['fixed_ips']:
                subnet_ids.add(fixed_ip['subnet_id'])
        LOG.debug("Needed subnet IDs: %s", subnet_ids)

        # Compare against the existing set of IDs.
        existing_ids = set([s.id for s in current_subnets])
        LOG.debug("Existing subnet IDs: %s", existing_ids)
        if subnet_ids == existing_ids:
            LOG.debug("Subnets unchanged")
            return None

        # Prepare required new subnet data.
        new_subnets = []
        for subnet_id in subnet_ids:
            # Check if we already have this subnet.
            existing = [s for s in current_subnets if s.id == subnet_id]
            if existing:
                # We do.  Assume subnet data hasn't changed.
                new_subnets.extend(existing)
            else:
                LOG.debug("Read subnet %s from etcd", subnet_id)

                # Read the data for this subnet.
                subnet_key = key_for_subnet(subnet_id)
                try:
                    response = self.client.read(subnet_key, consistent=True)
                    data = safe_decode_json(response.value, 'subnet')
                    LOG.debug("Subnet data: %s", data)
                    if not (isinstance(data, dict) and 'cidr' in data
                            and 'gateway_ip' in data):
                        # Subnet data was invalid.
                        LOG.warning("Invalid subnet data: %s => %s",
                                    response.value, data)
                        raise etcd.EtcdKeyNotFound()

                    # Convert to form expected by NetModel.
                    ip_version = 6 if ':' in data['cidr'] else 4
                    subnet = {
                        'enable_dhcp': True,
                        'ip_version': ip_version,
                        'cidr': data['cidr'],
                        'dns_nameservers': data.get('dns_servers') or [],
                        'id': subnet_id,
                        'gateway_ip': data['gateway_ip'],
                        'host_routes': []
                    }
                    if ip_version == 6:
                        subnet['ipv6_address_mode'] = constants.DHCPV6_STATEFUL
                        subnet['ipv6_ra_mode'] = constants.DHCPV6_STATEFUL

                    # Add this to the set to be returned.
                    new_subnets.append(subnet)
                except etcd.EtcdKeyNotFound:
                    LOG.warning("No data for subnet %s", subnet_id)

        return new_subnets
コード例 #19
0
    def on_endpoint_set(self, response, hostname, orchestrator,
                        workload_id, endpoint_id):
        """Handler for endpoint creations and updates.

        Endpoint data is, for example:

        { 'state': 'active' or 'inactive',
          'name': port['interface_name'],
          'mac': port['mac_address'],
          'profile_ids': port['security_groups'],
          'ipv4_nets': ['10.28.0.2/32'],
          'ipv4_gateway': '10.28.0.1',
          'ipv6_nets': ['2001:db8:1::2/128'],
          'ipv6_gateway': '2001:db8:1::1' }

        Port properties needed by DHCP code are:

        { 'id': <unique ID>,
          'network_id': <network ID>,
          'device_owner': 'calico',
          'device_id': <Linux interface name>,
          'fixed_ips': [ { 'subnet_id': <subnet ID>,
                           'ip_address': '10.28.0.2' } ],
          'mac_address: <MAC address>,
          'extra_dhcp_opts': ... (optional) }

        Network properties are:

        { 'subnets': [ <subnet object> ],
          'id': <network ID>,
          'namespace': None,
          'ports: [ <port object> ],
          'tenant_id': ? }

        Subnet properties are:

        { 'enable_dhcp': True,
          'ip_version': 4 or 6,
          'cidr': '10.28.0.0/24',
          'dns_nameservers': [],
          'id': <subnet ID>,
          'gateway_ip': <gateway IP address>,
          'host_routes': [],
          'ipv6_address_mode': 'dhcpv6-stateful' | 'dhcpv6-stateless',
          'ipv6_ra_mode': 'dhcpv6-stateful' | 'dhcpv6-stateless' }
        """

        # Get the endpoint data.
        endpoint = safe_decode_json(response.value, 'endpoint')
        if not (isinstance(endpoint, dict) and
                'ipv4_nets' in endpoint and
                'ipv4_subnet_ids' in endpoint and
                'ipv6_nets' in endpoint and
                'ipv6_subnet_ids' in endpoint and
                'name' in endpoint and
                'mac' in endpoint):
            # Endpoint data is invalid.
            LOG.warning("Invalid endpoint data: %s => %s",
                        response.value, endpoint)
            return

        # Construct NetModel port equivalent of Calico's endpoint data.
        fixed_ips = []
        dns_assignments = []
        fqdn = endpoint.get('fqdn')
        for ip_version in [4, 6]:
            # Generate the fixed IPs and DNS assignments for the current IP
            # version.
            for addrm, subnet_id in zip(endpoint['ipv%s_nets' % ip_version],
                                        endpoint['ipv%s_subnet_ids' %
                                                 ip_version]):
                ip_addr = addrm.split('/')[0]
                fixed_ips.append({'subnet_id': subnet_id,
                                  'ip_address': ip_addr})
                if fqdn:
                    dns_assignments.append({'hostname': fqdn.split('.')[0],
                                            'ip_address': ip_addr,
                                            'fqdn': fqdn})
        port = {'id': endpoint_id,
                'network_id': NETWORK_ID,
                'device_owner': 'calico',
                'device_id': endpoint['name'],
                'fixed_ips': fixed_ips,
                'mac_address': endpoint['mac'],
                'extra_dhcp_opts': []}
        if fqdn:
            port['dns_assignment'] = dns_assignments

        # Add this port into the NetModel.
        LOG.debug("new port: %s", port)
        self.agent.cache.put_port(dhcp.DictModel(port))

        # Now check for impact on subnets and DHCP driver.
        self.on_ports_changed()
コード例 #20
0
    def on_endpoint_set(self, response, hostname, orchestrator, workload_id,
                        endpoint_id):
        """Handler for endpoint creations and updates.

        Endpoint data is, for example:

        { 'state': 'active' or 'inactive',
          'name': port['interface_name'],
          'mac': port['mac_address'],
          'profile_ids': port['security_groups'],
          'ipv4_nets': ['10.28.0.2/32'],
          'ipv4_gateway': '10.28.0.1',
          'ipv6_nets': ['2001:db8:1::2/128'],
          'ipv6_gateway': '2001:db8:1::1' }

        Port properties needed by DHCP code are:

        { 'id': <unique ID>,
          'network_id': <network ID>,
          'device_owner': 'calico',
          'device_id': <Linux interface name>,
          'fixed_ips': [ { 'subnet_id': <subnet ID>,
                           'ip_address': '10.28.0.2' } ],
          'mac_address: <MAC address>,
          'extra_dhcp_opts': ... (optional) }

        Network properties are:

        { 'subnets': [ <subnet object> ],
          'id': <network ID>,
          'namespace': None,
          'ports: [ <port object> ],
          'tenant_id': ? }

        Subnet properties are:

        { 'enable_dhcp': True,
          'ip_version': 4 or 6,
          'cidr': '10.28.0.0/24',
          'dns_nameservers': [],
          'id': <subnet ID>,
          'gateway_ip': <gateway IP address>,
          'host_routes': [],
          'ipv6_address_mode': 'dhcpv6-stateful' | 'dhcpv6-stateless',
          'ipv6_ra_mode': 'dhcpv6-stateful' | 'dhcpv6-stateless' }
        """

        # Get the endpoint data.
        endpoint = safe_decode_json(response.value, 'endpoint')
        if not (isinstance(endpoint, dict) and 'ipv4_nets' in endpoint
                and 'ipv4_subnet_ids' in endpoint and 'ipv6_nets' in endpoint
                and 'ipv6_subnet_ids' in endpoint and 'name' in endpoint
                and 'mac' in endpoint):
            # Endpoint data is invalid.
            LOG.warning("Invalid endpoint data: %s => %s", response.value,
                        endpoint)
            return

        # Construct NetModel port equivalent of Calico's endpoint data.
        fixed_ips = []
        dns_assignments = []
        fqdn = endpoint.get('fqdn')
        for ip_version in [4, 6]:
            # Generate the fixed IPs and DNS assignments for the current IP
            # version.
            for addrm, subnet_id in zip(
                    endpoint['ipv%s_nets' % ip_version],
                    endpoint['ipv%s_subnet_ids' % ip_version]):
                ip_addr = addrm.split('/')[0]
                fixed_ips.append({
                    'subnet_id': subnet_id,
                    'ip_address': ip_addr
                })
                if fqdn:
                    dns_assignments.append({
                        'hostname': fqdn.split('.')[0],
                        'ip_address': ip_addr,
                        'fqdn': fqdn
                    })
        port = {
            'id': endpoint_id,
            'network_id': NETWORK_ID,
            'device_owner': 'calico',
            'device_id': endpoint['name'],
            'fixed_ips': fixed_ips,
            'mac_address': endpoint['mac'],
            'extra_dhcp_opts': []
        }
        if fqdn:
            port['dns_assignment'] = dns_assignments

        # Add this port into the NetModel.
        LOG.debug("new port: %s", port)
        self.agent.cache.put_port(dhcp.DictModel(port))

        # Now check for impact on subnets and DHCP driver.
        self.on_ports_changed()
コード例 #21
0
    def calculate_new_subnets(self, ports, current_subnets):
        """Calculate and return subnets needed for PORTS.

        Given a current set of PORTS that we need to provide DHCP for,
        calculate all the subnets that we need for those, and get their data
        either from CURRENT_SUBNETS or from reading etcd.

        If the new set of subnets is equivalent to what we already had in
        CURRENT_SUBNETS, return None.  Otherwise return the new set of
        subnets.
        """

        # Gather required subnet IDs.
        subnet_ids = set()
        for port in ports:
            for fixed_ip in port['fixed_ips']:
                subnet_ids.add(fixed_ip['subnet_id'])
        LOG.debug("Needed subnet IDs: %s", subnet_ids)

        # Compare against the existing set of IDs.
        existing_ids = set([s.id for s in current_subnets])
        LOG.debug("Existing subnet IDs: %s", existing_ids)
        if subnet_ids == existing_ids:
            LOG.debug("Subnets unchanged")
            return None

        # Prepare required new subnet data.
        new_subnets = []
        for subnet_id in subnet_ids:
            # Check if we already have this subnet.
            existing = [s for s in current_subnets if s.id == subnet_id]
            if existing:
                # We do.  Assume subnet data hasn't changed.
                new_subnets.extend(existing)
            else:
                LOG.debug("Read subnet %s from etcd", subnet_id)

                # Read the data for this subnet.
                subnet_key = key_for_subnet(subnet_id)
                try:
                    response = self.client.read(subnet_key, consistent=True)
                    data = safe_decode_json(response.value, 'subnet')
                    LOG.debug("Subnet data: %s", data)
                    if not (isinstance(data, dict) and
                            'cidr' in data and
                            'gateway_ip' in data):
                        # Subnet data was invalid.
                        LOG.warning("Invalid subnet data: %s => %s",
                                    response.value, data)
                        raise etcd.EtcdKeyNotFound()

                    # Convert to form expected by NetModel.
                    ip_version = 6 if ':' in data['cidr'] else 4
                    subnet = {'enable_dhcp': True,
                              'ip_version': ip_version,
                              'cidr': data['cidr'],
                              'dns_nameservers': data.get('dns_servers') or [],
                              'id': subnet_id,
                              'gateway_ip': data['gateway_ip'],
                              'host_routes': []}
                    if ip_version == 6:
                        subnet['ipv6_address_mode'] = constants.DHCPV6_STATEFUL
                        subnet['ipv6_ra_mode'] = constants.DHCPV6_STATEFUL

                    # Add this to the set to be returned.
                    new_subnets.append(subnet)
                except etcd.EtcdKeyNotFound:
                    LOG.warning("No data for subnet %s", subnet_id)

        return new_subnets