def setup_logging(conf):
- """
- Sets up the logging options for a log with supplied name
+ """Sets up the logging options for a log with supplied name.
:param conf: a cfg.ConfOpts object
"""
def load_paste_app(app_name):
- """
- Builds and returns a WSGI app from a paste config file.
+ """Builds and returns a WSGI app from a paste config file.
:param app_name: Name of the application to load
:raises RuntimeError when config file cannot be located or application
class QuantumException(OpenstackException):
- """Base Quantum Exception
+ """Base Quantum Exception.
To correctly use this class, inherit from it and define
a 'message' property. That message will get printf'd
with the keyword arguments provided to the constructor.
-
"""
message = _("An unknown exception occurred.")
class _AnsiColorizer(object):
- """
+ """ANSI colored texts.
+
A colorizer is an object that loosely wraps around a stream, allowing
callers to write text to the stream in a particular color.
self.stream = stream
def supported(cls, stream=sys.stdout):
- """
+ """Checks for coloring terminal support.
+
A class method that returns True if the current platform supports
coloring terminal output using this method. Returns False otherwise.
"""
supported = classmethod(supported)
def write(self, text, color):
- """
- Write the given text to the stream in the given color.
+ """Write the given text to the stream in the given color.
@param text: Text to be written to the stream.
class _Win32Colorizer(object):
- """
- See _AnsiColorizer docstring.
- """
+ """See _AnsiColorizer docstring."""
def __init__(self, stream):
from win32console import GetStdHandle, STD_OUT_HANDLE
from win32console import FOREGROUND_RED, FOREGROUND_BLUE
class _NullColorizer(object):
- """
- See _AnsiColorizer docstring.
- """
+ """See _AnsiColorizer docstring."""
def __init__(self, stream):
self.stream = stream
# NOTE(vish, tfukushima): copied from unittest with edit to add color
def addError(self, test, err):
"""Overrides normal addError to add support for errorClasses.
+
If the exception is a registered class, the error will be added
to the list for that class, not errors.
"""
def find_config_file(options, config_file):
- """
- Return the first config file found.
+ """Return the first config file found.
We search for the paste config file in the following order:
* If --config-file option is used, use that
class AgentExtRpcCallback(object):
"""Processes the rpc report in plugin implementations."""
+
RPC_API_VERSION = '1.0'
START_TIME = timeutils.utcnow()
class NetworkDhcpAgentBinding(model_base.BASEV2):
"""Represents binding between quantum networks and DHCP agents."""
+
network_id = sa.Column(sa.String(36),
sa.ForeignKey("networks.id", ondelete='CASCADE'),
primary_key=True)
class RouterL3AgentBinding(model_base.BASEV2, models_v2.HasId):
"""Represents binding between quantum routers and L3 agents."""
+
router_id = sa.Column(sa.String(36),
sa.ForeignKey("routers.id", ondelete='CASCADE'))
l3_agent = orm.relation(agents_db.Agent)
return {'agents': []}
def add_router_to_l3_agent(self, context, id, router_id):
- """Add a l3 agent to host a router.
- """
+ """Add a l3 agent to host a router."""
router = self.get_router(context, router_id)
with context.session.begin(subtransactions=True):
agent_db = self._get_agent(context, id)
context, routers, agent_db.host)
def remove_router_from_l3_agent(self, context, id, router_id):
- """Remove the router from l3 agent. After it, the router
- will be non-hosted until there is update which
+ """Remove the router from l3 agent.
+
+ After it, the router will be non-hosted until there is update which
lead to re schedule or be added to another agent manually.
"""
agent = self._get_agent(context, id)
self, context, router)
def schedule_routers(self, context, routers):
- """Schedule the routers to l3 agents.
- """
+ """Schedule the routers to l3 agents."""
for router in routers:
self.schedule_router(context, router)
class MySQLPingListener(object):
-
- """
- Ensures that MySQL connections checked out of the
- pool are alive.
+ """Ensures that MySQL connections checked out of the pool are alive.
Borrowed from:
http://groups.google.com/group/sqlalchemy/msg/a4ce563d802c929f
class SqliteForeignKeysListener(PoolListener):
- """
- Ensures that the foreign key constraints are enforced in SQLite.
+ """Ensures that the foreign key constraints are enforced in SQLite.
The foreign key constraints are disabled by default in SQLite,
so the foreign key constraints will be enabled here for every
def configure_db():
- """
- Establish the database, create an engine if needed, and
- register the models.
+ """Configure database.
+
+ Establish the database, create an engine if needed, and register
+ the models.
"""
global _ENGINE
if not _ENGINE:
def greenthread_yield(dbapi_con, con_record):
- """
- Ensure other greenthreads get a chance to execute by forcing a context
- switch. With common database backends (eg MySQLdb and sqlite), there is
- no implicit yield caused by network I/O since they are implemented by
- C libraries that eventlet cannot monkey patch.
+ """Ensure other greenthreads get a chance to execute.
+
+ This is done by forcing a context switch. With common database
+ backends (eg MySQLdb and sqlite), there is no implicit yield caused
+ by network I/O since they are implemented by C libraries that
+ eventlet cannot monkey patch.
"""
greenthread.sleep(0)
class QuantumDbPluginV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
- """A class that implements the v2 Quantum plugin interface
- using SQLAlchemy models. Whenever a non-read call happens
- the plugin will call an event handler class method (e.g.,
- network_created()). The result is that this class can be
- sub-classed by other classes that add custom behaviors on
- certain events.
+ """V2 Quantum plugin interface implementation using SQLAlchemy models.
+
+ Whenever a non-read call happens the plugin will call an event handler
+ class method (e.g., network_created()). The result is that this class
+ can be sub-classed by other classes that add custom behaviors on certain
+ events.
"""
# This attribute specifies whether the plugin supports or not
Verifies the specified CIDR does not overlap with the ones defined
for the other subnets specified for this network, or with any other
CIDR if overlapping IPs are disabled.
-
"""
new_subnet_ipset = netaddr.IPSet([new_subnet_cidr])
if cfg.CONF.allow_overlapping_ips:
ie: constituted by valid and appropriately ordered IP addresses.
Also, verify pools do not overlap among themselves.
Finally, verify that each range fall within the subnet's CIDR.
-
"""
-
subnet = netaddr.IPNetwork(subnet_cidr)
subnet_first_ip = netaddr.IPAddress(subnet.first + 1)
subnet_last_ip = netaddr.IPAddress(subnet.last - 1)
Pools are defined by the 'allocation_pools' attribute,
a list of dict objects with 'start' and 'end' keys for
defining the pool range.
-
"""
-
pools = []
# Auto allocate the pool around gateway_ip
net = netaddr.IPNetwork(subnet['cidr'])
return self._make_subnet_dict(subnet)
def update_subnet(self, context, id, subnet):
- """Update the subnet with new info. The change however will not be
- realized until the client renew the dns lease or we support
- gratuitous DHCP offers
- """
+ """Update the subnet with new info.
+ The change however will not be realized until the client renew the
+ dns lease or we support gratuitous DHCP offers
+ """
s = subnet['subnet']
db_subnet = self._get_subnet(context, id)
# Fill 'ip_version' and 'allocation_pools' fields with the current
class Router(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
"""Represents a v2 quantum router."""
+
name = sa.Column(sa.String(255))
status = sa.Column(sa.String(16))
admin_state_up = sa.Column(sa.Boolean)
class FloatingIP(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
- """Represents a floating IP, which may or many not be
- allocated to a tenant, and may or may not be associated with
- an internal port/ip address/router.
+ """Represents a floating IP address.
+
+ This IP address may or many not be allocated to a tenant, and may or
+ may not be associated with an internal port/ip address/router.
"""
+
floating_ip_address = sa.Column(sa.String(64), nullable=False)
floating_network_id = sa.Column(sa.String(36), nullable=False)
floating_port_id = sa.Column(sa.String(36), sa.ForeignKey('ports.id'),
port_id=internal_port['id'])
def get_assoc_data(self, context, fip, floating_network_id):
- """When a floating IP is associated with an internal port,
+ """Determine/extract data associated with the internal port.
+
+ When a floating IP is associated with an internal port,
we need to extract/determine some data associated with the
internal port, including the internal_ip_address, and router_id.
We also need to confirm that this internal port is owned by the
filters=filters)
def prevent_l3_port_deletion(self, context, port_id):
- """Checks to make sure a port is allowed to be deleted, raising
- an exception if this is not the case. This should be called by
- any plugin when the API requests the deletion of a port, since
- some ports for L3 are not intended to be deleted directly via a
- DELETE to /ports, but rather via other API calls that perform the
- proper deletion checks.
+ """Checks to make sure a port is allowed to be deleted.
+
+ Raises an exception if this is not the case. This should be called by
+ any plugin when the API requests the deletion of a port, since some
+ ports for L3 are not intended to be deleted directly via a DELETE
+ to /ports, but rather via other API calls that perform the proper
+ deletion checks.
"""
port_db = self._get_port(context, port_id)
if port_db['device_owner'] in [DEVICE_OWNER_ROUTER_INTF,
class SessionPersistence(model_base.BASEV2):
+
vip_id = sa.Column(sa.String(36),
sa.ForeignKey("vips.id"),
primary_key=True)
class PoolStatistics(model_base.BASEV2):
"""Represents pool statistics."""
+
pool_id = sa.Column(sa.String(36), sa.ForeignKey("pools.id"),
primary_key=True)
bytes_in = sa.Column(sa.Integer, nullable=False)
class Vip(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
"""Represents a v2 quantum loadbalancer vip."""
+
name = sa.Column(sa.String(255))
description = sa.Column(sa.String(255))
port_id = sa.Column(sa.String(36), sa.ForeignKey('ports.id'))
class Member(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
"""Represents a v2 quantum loadbalancer member."""
+
pool_id = sa.Column(sa.String(36), sa.ForeignKey("pools.id"),
nullable=False)
address = sa.Column(sa.String(64), nullable=False)
class Pool(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
"""Represents a v2 quantum loadbalancer pool."""
+
vip_id = sa.Column(sa.String(36), sa.ForeignKey("vips.id"))
name = sa.Column(sa.String(255))
description = sa.Column(sa.String(255))
class HealthMonitor(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
"""Represents a v2 quantum loadbalancer healthmonitor."""
+
type = sa.Column(sa.Enum("PING", "TCP", "HTTP", "HTTPS",
name="healthmontiors_type"),
nullable=False)
class PoolMonitorAssociation(model_base.BASEV2):
- """
- Represents the many-to-many association between pool and
- healthMonitor classes
- """
+ """Many-to-many association between pool and healthMonitor classes."""
+
pool_id = sa.Column(sa.String(36),
sa.ForeignKey("pools.id"),
primary_key=True)
class LoadBalancerPluginDb(LoadBalancerPluginBase):
- """
- A class that wraps the implementation of the Quantum
- loadbalancer plugin database access interface using SQLAlchemy models.
+ """Wraps loadbalancer with SQLAlchemy models.
+
+ A class that wraps the implementation of the Quantum loadbalancer
+ plugin database access interface using SQLAlchemy models.
"""
@property
def _check_session_persistence_info(self, info):
"""Performs sanity check on session persistence info.
+
:param info: Session persistence info
"""
if info['type'] == 'APP_COOKIE':
class QuantumBase(object):
"""Base class for Quantum Models."""
+
__table_args__ = {'mysql_engine': 'InnoDB'}
def __setitem__(self, key, value):
def iteritems(self):
"""Make the model object behave like a dict.
+
Includes attributes from joins.
"""
local = dict(self)
class HasTenant(object):
"""Tenant mixin, add to subclasses that have a tenant."""
+
# NOTE(jkoelker) tenant_id is just a free form string ;(
tenant_id = sa.Column(sa.String(255))
class HasId(object):
"""id mixin, add to subclasses that have an id."""
+
id = sa.Column(sa.String(36),
primary_key=True,
default=uuidutils.generate_uuid)
only done if the range is contiguous. If not, the first_ip will be
the same as the last_ip. When adjacent ips are recycled the ranges
will be merged.
-
"""
+
allocation_pool_id = sa.Column(sa.String(36),
sa.ForeignKey('ipallocationpools.id',
ondelete="CASCADE"),
class IPAllocation(model_base.BASEV2):
"""Internal representation of allocated IP addresses in a Quantum subnet.
"""
+
port_id = sa.Column(sa.String(36), sa.ForeignKey('ports.id',
ondelete="CASCADE"),
nullable=True)
class Route(object):
"""mixin of a route."""
+
destination = sa.Column(sa.String(64), nullable=False, primary_key=True)
nexthop = sa.Column(sa.String(64), nullable=False, primary_key=True)
class SubnetRoute(model_base.BASEV2, Route):
+
subnet_id = sa.Column(sa.String(36),
sa.ForeignKey('subnets.id',
ondelete="CASCADE"),
class Port(model_base.BASEV2, HasId, HasTenant):
"""Represents a port on a quantum v2 network."""
+
name = sa.Column(sa.String(255))
network_id = sa.Column(sa.String(36), sa.ForeignKey("networks.id"),
nullable=False)
class DNSNameServer(model_base.BASEV2):
"""Internal representation of a DNS nameserver."""
+
address = sa.Column(sa.String(128), nullable=False, primary_key=True)
subnet_id = sa.Column(sa.String(36),
sa.ForeignKey('subnets.id',
When a subnet is created the first and last entries will be created. These
are used for the IP allocation.
"""
+
name = sa.Column(sa.String(255))
network_id = sa.Column(sa.String(36), sa.ForeignKey('networks.id'))
ip_version = sa.Column(sa.Integer, nullable=False)
class Network(model_base.BASEV2, HasId, HasTenant):
"""Represents a v2 quantum network."""
+
name = sa.Column(sa.String(255))
ports = orm.relationship(Port, backref='networks')
subnets = orm.relationship(Subnet, backref='networks')
return self._fields(res, fields)
def _determine_port_security_and_has_ip(self, context, port):
- """Returns a tuple of (port_security_enabled, has_ip) where
- port_security_enabled and has_ip are bools. Port_security is the
- value assocated with the port if one is present otherwise the value
- associated with the network is returned. has_ip is if the port is
- associated with an ip or not.
+ """Returns a tuple of booleans (port_security_enabled, has_ip).
+
+ Port_security is the value assocated with the port if one is present
+ otherwise the value associated with the network is returned. has_ip is
+ if the port is associated with an ip or not.
"""
has_ip = self._ip_on_port(port)
# we don't apply security groups for dhcp, router
class DbQuotaDriver(object):
- """
- Driver to perform necessary checks to enforce quotas and obtain
- quota information. The default driver utilizes the local
- database.
+ """Driver to perform necessary checks to enforce quotas and obtain quota
+ information.
+
+ The default driver utilizes the local database.
"""
@staticmethod
def get_tenant_quotas(context, resources, tenant_id):
- """
- Given a list of resources, retrieve the quotas for the given
+ """Given a list of resources, retrieve the quotas for the given
tenant.
:param context: The request context, for access checks.
@staticmethod
def get_all_quotas(context, resources):
- """
- Given a list of resources, retrieve the quotas for the all
- tenants.
+ """Given a list of resources, retrieve the quotas for the all tenants.
:param context: The request context, for access checks.
:param resources: A dictionary of the registered resource keys.
:return quotas: list of dict of tenant_id:, resourcekey1:
resourcekey2: ...
"""
-
tenant_default = dict((key, resource.default)
for key, resource in resources.items())
context.session.add(tenant_quota)
def _get_quotas(self, context, tenant_id, resources, keys):
- """
+ """Retrieves the quotas for specific resources.
+
A helper method which retrieves the quotas for the specific
resources identified by keys, and which apply to the current
context.
:param keys: A list of the desired quotas to retrieve.
"""
-
desired = set(keys)
sub_resources = dict((k, v) for k, v in resources.items()
if k in desired)
class SecurityGroup(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
"""Represents a v2 quantum security group."""
+
name = sa.Column(sa.String(255))
description = sa.Column(sa.String(255))
class SecurityGroupPortBinding(model_base.BASEV2):
"""Represents binding between quantum ports and security profiles."""
+
port_id = sa.Column(sa.String(36),
sa.ForeignKey("ports.id",
ondelete='CASCADE'),
class SecurityGroupRule(model_base.BASEV2, models_v2.HasId,
models_v2.HasTenant):
"""Represents a v2 quantum security group rule."""
+
security_group_id = sa.Column(sa.String(36),
sa.ForeignKey("securitygroups.id",
ondelete="CASCADE"),
def create_security_group(self, context, security_group, default_sg=False):
"""Create security group.
+
If default_sg is true that means we are a default security group for
a given tenant if it does not exist.
"""
filters=filters)
def get_security_group(self, context, id, fields=None, tenant_id=None):
- """Tenant id is given to handle the case when we
- are creating a security group rule on behalf of another use.
+ """Tenant id is given to handle the case when creating a security
+ group rule on behalf of another use.
"""
if tenant_id:
bulk_rule)[0]
def _validate_security_group_rules(self, context, security_group_rule):
- """Check that rules being installed all belong to the same security
+ """Check that rules being installed.
+
+ Check that all rules belong to the same security
group, remote_group_id/security_group_id belong to the same tenant,
and rules are valid.
"""
class SecurityGroupServerRpcCallbackMixin(object):
- """A mix-in that enable SecurityGroup agent
-
- support in plugin implementations.
+ """A mix-in that enable SecurityGroup agent support in plugin
+ implementations.
"""
def security_group_rules_for_devices(self, context, **kwargs):
class ExecProbe(ProbeCommand):
- """Exec commands on the namespace of the probe
- """
+ """Exec commands on the namespace of the probe."""
log = logging.getLogger(__name__ + '.ExecProbe')
class PingAll(ProbeCommand):
- """Ping all fixed_ip
- """
+ """Ping all fixed_ip."""
log = logging.getLogger(__name__ + '.ExecProbe')
@abstractmethod
def delete_agent(self, context, id):
"""Delete agent.
+
Agents register themselves on reporting state.
But if a agent does not report its status
for a long time (for example, it is dead for ever. ),
@abstractmethod
def update_agent(self, context, agent):
"""Disable or Enable the agent.
- Discription also can be updated.
- Some agents cannot be disabled,
- such as plugins, services.
- An error code should be reported in this case.
+ Discription also can be updated. Some agents cannot be disabled, such
+ as plugins, services. An error code should be reported in this case.
@raise exceptions.BadRequest:
"""
pass
class Portsecurity(object):
- """Extension class supporting port security
- """
+ """Extension class supporting port security."""
@classmethod
def get_name(cls):