Ejemplo n.º 1
0
class IPPolicyCIDR(BASEV2, HasId):
    __tablename__ = "quark_ip_policy_cidrs"
    ip_policy_id = sa.Column(sa.String(36), sa.ForeignKey(
        "quark_ip_policy.id", ondelete="CASCADE"))
    cidr = sa.Column(sa.String(64))
    first_ip = sa.Column(custom_types.INET())
    last_ip = sa.Column(custom_types.INET())
Ejemplo n.º 2
0
class Subnet(BASEV2, models.HasId, models.HasTenant, IsHazTags):
    """Upstream model for IPs.

    Subnet -> has_many(IPAllocationPool)
    IPAllocationPool -> has_many(IPAvailabilityRange)
        As well as first and last _ip markers for some unknown reason
        first_ip is min(ranges), last_ip is max(ranges)
    IPAvailabilityRange -> belongs_to(IPAllocationPool)
        Also has first and last _ip, but only for the range
    IPAllocation -> belongs_to(port, subnet, network) but NOT IPAllocationPool

    IPAllocationPool and Range seem superfluous. Just create intelligent CIDRs
    for your subnet
    """
    __tablename__ = "quark_subnets"
    name = sa.Column(sa.String(255))
    network_id = sa.Column(sa.String(36), sa.ForeignKey('quark_networks.id'))
    _cidr = sa.Column(sa.String(64), nullable=False)

    @hybrid.hybrid_property
    def cidr(self):
        return self._cidr

    @cidr.setter
    def cidr(self, val):
        self._cidr = val
        preip = netaddr.IPNetwork(val)
        self.ip_version = preip.version
        ip = netaddr.IPNetwork(val).ipv6()
        self.first_ip = ip.first
        self.last_ip = ip.last
        self.next_auto_assign_ip = self.first_ip

    @cidr.expression
    def cidr(cls):
        return Subnet._cidr

    first_ip = sa.Column(custom_types.INET())
    last_ip = sa.Column(custom_types.INET())
    ip_version = sa.Column(sa.Integer())
    next_auto_assign_ip = sa.Column(custom_types.INET())

    allocated_ips = orm.relationship(IPAddress,
                                     primaryjoin='and_(Subnet.id=='
                                     'IPAddress.subnet_id, '
                                     'IPAddress._deallocated!=1)',
                                     backref="subnet")
    routes = orm.relationship(Route,
                              primaryjoin="Route.subnet_id==Subnet.id",
                              backref='subnet',
                              cascade='delete')
    enable_dhcp = sa.Column(sa.Boolean(), default=False)
    dns_nameservers = orm.relationship(
        DNSNameserver,
        primaryjoin="DNSNameserver.subnet_id==Subnet.id",
        backref='subnet',
        cascade='delete')
    ip_policy = orm.relationship("IPPolicy", uselist=False, backref="subnet")
Ejemplo n.º 3
0
class IPPolicy(BASEV2, models.HasId, models.HasTenant):
    __tablename__ = "quark_ip_policy"
    networks = orm.relationship(
        "Network",
        primaryjoin="IPPolicy.id==Network.ip_policy_id",
        backref="ip_policy")
    subnets = orm.relationship(
        "Subnet",
        primaryjoin="IPPolicy.id==Subnet.ip_policy_id",
        backref="ip_policy")
    exclude = orm.relationship(
        "IPPolicyCIDR",
        primaryjoin="IPPolicy.id==IPPolicyCIDR.ip_policy_id",
        backref="ip_policy")
    name = sa.Column(sa.String(255), nullable=True)
    description = sa.Column(sa.String(255), nullable=True)
    size = sa.Column(custom_types.INET())

    @staticmethod
    def get_ip_policy_cidrs(subnet):
        ip_policy = subnet["ip_policy"] or {}
        ip_policies = ip_policy.get("exclude", [])
        ip_policy_cidrs = [ip_policy_cidr.cidr
                           for ip_policy_cidr in ip_policies]
        return netaddr.IPSet(ip_policy_cidrs)
Ejemplo n.º 4
0
class IPAddress(BASEV2, models.HasId):
    """More closely emulate the melange version of the IP table.

    We always mark the record as deallocated rather than deleting it.
    Gives us an IP address owner audit log for free, essentially.
    """
    __tablename__ = "quark_ip_addresses"
    __table_args__ = (sa.UniqueConstraint("subnet_id", "address",
                                          name="subnet_id_address"),
                      TABLE_KWARGS)

    address_readable = sa.Column(sa.String(128), nullable=False)
    address = sa.Column(custom_types.INET(), nullable=False, index=True)
    subnet_id = sa.Column(sa.String(36),
                          sa.ForeignKey("quark_subnets.id",
                                        ondelete="CASCADE"))
    network_id = sa.Column(sa.String(36),
                           sa.ForeignKey("quark_networks.id",
                                         ondelete="CASCADE"))
    version = sa.Column(sa.Integer(), index=True)
    allocated_at = sa.Column(sa.DateTime())
    subnet = orm.relationship("Subnet")
    # Need a constant to facilitate the indexed search for new IPs
    _deallocated = sa.Column(sa.Boolean())
    # Legacy data
    used_by_tenant_id = sa.Column(sa.String(255))

    @hybrid.hybrid_property
    def deallocated(self):
        return self._deallocated and not self.ports

    @deallocated.setter
    def deallocated(self, val):
        self._deallocated = val
        self.deallocated_at = None
        if val:
            self.deallocated_at = timeutils.utcnow()
            self.allocated_at = None

    # TODO(jkoelker) update the expression to use the jointable as well
    @deallocated.expression
    def deallocated(cls):
        return IPAddress._deallocated

    def formatted(self):
        ip = netaddr.IPAddress(self.address_readable)
        if self.version == 4:
            return str(ip.ipv4())
        return str(ip.ipv6())

    deallocated_at = sa.Column(sa.DateTime(), index=True)
Ejemplo n.º 5
0
class Subnet(BASEV2, HasId, IsHazTags, HasTenant):
    """Upstream model for IPs.

    Subnet -> has_many(IPAllocationPool)
    IPAllocationPool -> has_many(IPAvailabilityRange)
        As well as first and last _ip markers for some unknown reason
        first_ip is min(ranges), last_ip is max(ranges)
    IPAvailabilityRange -> belongs_to(IPAllocationPool)
        Also has first and last _ip, but only for the range
    IPAllocation -> belongs_to(port, subnet, network) but NOT IPAllocationPool

    IPAllocationPool and Range seem superfluous. Just create intelligent CIDRs
    for your subnet
    """
    __tablename__ = "quark_subnets"
    id = sa.Column(sa.String(36), primary_key=True)
    name = sa.Column(sa.String(255))
    network_id = sa.Column(sa.String(36), sa.ForeignKey('quark_networks.id'))
    _cidr = sa.Column(sa.String(64), nullable=False)
    _allocation_pool_cache = orm.deferred(sa.Column(sa.Text(), nullable=True))
    segment_id = sa.Column(sa.String(255), index=True)

    @hybrid.hybrid_property
    def cidr(self):
        return self._cidr

    @hybrid.hybrid_property
    def allocation_pools(self):
        _cache = self.get("_allocation_pool_cache")
        if _cache:
            pools = json.loads(_cache)
            return pools
        else:
            if self["ip_policy"]:
                ip_policy_cidrs = self["ip_policy"].get_cidrs_ip_set()
            else:
                ip_policy_cidrs = netaddr.IPSet([])

            cidr = netaddr.IPSet([netaddr.IPNetwork(self["cidr"])])
            allocatable = cidr - ip_policy_cidrs
            pools = _pools_from_cidr(allocatable)
            return pools

    @cidr.setter
    def cidr(self, val):
        self._cidr = val
        preip = netaddr.IPNetwork(val)
        self.ip_version = preip.version
        ip = netaddr.IPNetwork(val).ipv6()
        self.first_ip = ip.first
        self.last_ip = ip.last
        self.next_auto_assign_ip = self.first_ip

    @cidr.expression
    def cidr(cls):
        return Subnet._cidr

    first_ip = sa.Column(custom_types.INET())
    last_ip = sa.Column(custom_types.INET())
    ip_version = sa.Column(sa.Integer())
    next_auto_assign_ip = sa.Column(custom_types.INET())

    allocated_ips = orm.relationship(IPAddress,
                                     primaryjoin='and_(Subnet.id=='
                                     'IPAddress.subnet_id,'
                                     'IPAddress._deallocated != 1)')
    generated_ips = orm.relationship(IPAddress,
                                     primaryjoin='Subnet.id=='
                                     'IPAddress.subnet_id')
    routes = orm.relationship(Route, primaryjoin="Route.subnet_id==Subnet.id",
                              backref='subnet', cascade='delete')
    enable_dhcp = sa.Column(sa.Boolean(), default=False)
    dns_nameservers = orm.relationship(
        DNSNameserver,
        primaryjoin="DNSNameserver.subnet_id==Subnet.id",
        backref='subnet',
        cascade='delete')
    ip_policy_id = sa.Column(sa.String(36),
                             sa.ForeignKey("quark_ip_policy.id"))
    # Legacy data
    do_not_use = sa.Column(sa.Boolean(), default=False)
Ejemplo n.º 6
0
class DNSNameserver(BASEV2, HasTenant, HasId, IsHazTags):
    __tablename__ = "quark_dns_nameservers"
    ip = sa.Column(custom_types.INET())
    subnet_id = sa.Column(sa.String(36), sa.ForeignKey("quark_subnets.id",
                                                       ondelete="CASCADE"))
Ejemplo n.º 7
0
class IPAddress(BASEV2, HasId):
    """More closely emulate the melange version of the IP table.

    We always mark the record as deallocated rather than deleting it.
    Gives us an IP address owner audit log for free, essentially.
    """
    __tablename__ = "quark_ip_addresses"
    __table_args__ = (sa.UniqueConstraint("subnet_id", "address",
                                          name="subnet_id_address"),
                      TABLE_KWARGS)
    address_readable = sa.Column(sa.String(128), nullable=False)
    address = sa.Column(custom_types.INET(), nullable=False, index=True)
    subnet_id = sa.Column(sa.String(36),
                          sa.ForeignKey("quark_subnets.id",
                                        ondelete="CASCADE"))
    network_id = sa.Column(sa.String(36),
                           sa.ForeignKey("quark_networks.id",
                                         ondelete="CASCADE"))
    network = orm.relationship("Network")
    version = sa.Column(sa.Integer(), index=True)
    allocated_at = sa.Column(sa.DateTime())
    subnet = orm.relationship("Subnet")
    # Need a constant to facilitate the indexed search for new IPs
    _deallocated = sa.Column(sa.Boolean())
    # Legacy data
    used_by_tenant_id = sa.Column(sa.String(255))

    address_type = sa.Column(sa.Enum(ip_types.FIXED, ip_types.FLOATING,
                                     ip_types.SHARED, ip_types.SCALING,
                             name="quark_ip_address_types"))
    associations = orm.relationship(PortIpAssociation, backref="ip_address")
    transaction_id = sa.Column(sa.Integer(),
                               sa.ForeignKey("quark_transactions.id"),
                               nullable=True)
    lock_id = sa.Column(sa.Integer(),
                        sa.ForeignKey("quark_locks.id"),
                        nullable=True)

    def is_shared(self):
        return self.address_type == ip_types.SHARED

    def has_any_shared_owner(self):
        for assoc in self["associations"]:
            if assoc.service != 'none' and assoc.service is not None:
                return True
        return False

    def set_service_for_port(self, port, service):
        for assoc in self["associations"]:
            if assoc.port_id == port["id"]:
                assoc.service = service

    def get_service_for_port(self, port):
        for assoc in self["associations"]:
            if assoc.port_id == port["id"]:
                return assoc.service

    def enabled_for_port(self, port):
        for assoc in self["associations"]:
            if assoc.port_id == port["id"]:
                return assoc.enabled

    @hybrid.hybrid_property
    def deallocated(self):
        return self._deallocated and not self.ports

    @deallocated.setter
    def deallocated(self, val):
        self._deallocated = val
        self.deallocated_at = None
        if val:
            self.deallocated_at = timeutils.utcnow()
            self.allocated_at = None

    # TODO(jkoelker) update the expression to use the jointable as well
    @deallocated.expression
    def deallocated(cls):
        return IPAddress._deallocated

    def formatted(self):
        ip = netaddr.IPAddress(self.address_readable)
        if self.version == 4:
            return str(ip.ipv4())
        return str(ip.ipv6())

    deallocated_at = sa.Column(sa.DateTime(), index=True)
    fixed_ip = None
Ejemplo n.º 8
0
 def setUp(self):
     super(TestDBCustomTypesINET, self).setUp()
     self.inet = custom_types.INET()
Ejemplo n.º 9
0
class IPPolicyRule(BASEV2, models.HasId):
    __tablename__ = "quark_ip_policy_rules"
    ip_policy_id = sa.Column(
        sa.String(36), sa.ForeignKey("quark_ip_policy.id", ondelete="CASCADE"))
    address = sa.Column(custom_types.INET())
    prefix = sa.Column(sa.Integer())