/usr/lib/python2.7/dist-packages/networking_arista/common/db_lib.py is in python-networking-arista 2017.2.2-2ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 | # Copyright (c) 2013 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from neutron_lib import constants as n_const
from neutron_lib import context as nctx
from neutron_lib.plugins.ml2 import api as driver_api
import neutron.db.api as db
from neutron.db import db_base_plugin_v2
from neutron.db.models import segment as segment_models
from neutron.db import securitygroups_db as sec_db
from neutron.db import segments_db
from neutron.plugins.ml2 import models as ml2_models
from neutron.services.trunk import models as trunk_models
from networking_arista.common import db as db_models
VLAN_SEGMENTATION = 'vlan'
def remember_tenant(tenant_id):
"""Stores a tenant information in repository.
:param tenant_id: globally unique neutron tenant identifier
"""
session = db.get_writer_session()
with session.begin():
tenant = (session.query(db_models.AristaProvisionedTenants).
filter_by(tenant_id=tenant_id).first())
if not tenant:
tenant = db_models.AristaProvisionedTenants(tenant_id=tenant_id)
session.add(tenant)
def forget_tenant(tenant_id):
"""Removes a tenant information from repository.
:param tenant_id: globally unique neutron tenant identifier
"""
session = db.get_writer_session()
with session.begin():
(session.query(db_models.AristaProvisionedTenants).
filter_by(tenant_id=tenant_id).
delete())
def get_all_tenants():
"""Returns a list of all tenants stored in repository."""
session = db.get_reader_session()
with session.begin():
return session.query(db_models.AristaProvisionedTenants).all()
def num_provisioned_tenants():
"""Returns number of tenants stored in repository."""
session = db.get_reader_session()
with session.begin():
return session.query(db_models.AristaProvisionedTenants).count()
def remember_vm(vm_id, host_id, port_id, network_id, tenant_id):
"""Stores all relevant information about a VM in repository.
:param vm_id: globally unique identifier for VM instance
:param host_id: ID of the host where the VM is placed
:param port_id: globally unique port ID that connects VM to network
:param network_id: globally unique neutron network identifier
:param tenant_id: globally unique neutron tenant identifier
"""
session = db.get_writer_session()
with session.begin():
vm = db_models.AristaProvisionedVms(
vm_id=vm_id,
host_id=host_id,
port_id=port_id,
network_id=network_id,
tenant_id=tenant_id)
session.add(vm)
def forget_all_ports_for_network(net_id):
"""Removes all ports for a given network fron repository.
:param net_id: globally unique network ID
"""
session = db.get_writer_session()
with session.begin():
(session.query(db_models.AristaProvisionedVms).
filter_by(network_id=net_id).delete())
def update_port(vm_id, host_id, port_id, network_id, tenant_id):
"""Updates the port details in the database.
:param vm_id: globally unique identifier for VM instance
:param host_id: ID of the new host where the VM is placed
:param port_id: globally unique port ID that connects VM to network
:param network_id: globally unique neutron network identifier
:param tenant_id: globally unique neutron tenant identifier
"""
session = db.get_writer_session()
with session.begin():
port = session.query(db_models.AristaProvisionedVms).filter_by(
port_id=port_id).first()
if port:
# Update the VM's host id
port.host_id = host_id
port.vm_id = vm_id
port.network_id = network_id
port.tenant_id = tenant_id
def forget_port(port_id, host_id):
"""Deletes the port from the database
:param port_id: globally unique port ID that connects VM to network
:param host_id: host to which the port is bound to
"""
session = db.get_writer_session()
with session.begin():
session.query(db_models.AristaProvisionedVms).filter_by(
port_id=port_id,
host_id=host_id).delete()
def remember_network_segment(tenant_id,
network_id, segmentation_id, segment_id):
"""Stores all relevant information about a Network in repository.
:param tenant_id: globally unique neutron tenant identifier
:param network_id: globally unique neutron network identifier
:param segmentation_id: segmentation id that is assigned to the network
:param segment_id: globally unique neutron network segment identifier
"""
session = db.get_writer_session()
with session.begin():
net = db_models.AristaProvisionedNets(
tenant_id=tenant_id,
id=segment_id,
network_id=network_id,
segmentation_id=segmentation_id)
session.add(net)
def forget_network_segment(tenant_id, network_id, segment_id=None):
"""Deletes all relevant information about a Network from repository.
:param tenant_id: globally unique neutron tenant identifier
:param network_id: globally unique neutron network identifier
:param segment_id: globally unique neutron network segment identifier
"""
filters = {
'tenant_id': tenant_id,
'network_id': network_id
}
if segment_id:
filters['id'] = segment_id
session = db.get_writer_session()
with session.begin():
(session.query(db_models.AristaProvisionedNets).
filter_by(**filters).delete())
def get_segmentation_id(tenant_id, network_id):
"""Returns Segmentation ID (VLAN) associated with a network.
:param tenant_id: globally unique neutron tenant identifier
:param network_id: globally unique neutron network identifier
"""
session = db.get_reader_session()
with session.begin():
net = (session.query(db_models.AristaProvisionedNets).
filter_by(tenant_id=tenant_id,
network_id=network_id).first())
return net.segmentation_id if net else None
def is_vm_provisioned(vm_id, host_id, port_id,
network_id, tenant_id):
"""Checks if a VM is already known to EOS
:returns: True, if yes; False otherwise.
:param vm_id: globally unique identifier for VM instance
:param host_id: ID of the host where the VM is placed
:param port_id: globally unique port ID that connects VM to network
:param network_id: globally unique neutron network identifier
:param tenant_id: globally unique neutron tenant identifier
"""
session = db.get_reader_session()
with session.begin():
num_vm = (session.query(db_models.AristaProvisionedVms).
filter_by(tenant_id=tenant_id,
vm_id=vm_id,
port_id=port_id,
network_id=network_id,
host_id=host_id).count())
return num_vm > 0
def is_port_provisioned(port_id, host_id=None):
"""Checks if a port is already known to EOS
:returns: True, if yes; False otherwise.
:param port_id: globally unique port ID that connects VM to network
:param host_id: host to which the port is bound to
"""
filters = {
'port_id': port_id
}
if host_id:
filters['host_id'] = host_id
session = db.get_reader_session()
with session.begin():
num_ports = (session.query(db_models.AristaProvisionedVms).
filter_by(**filters).count())
return num_ports > 0
def is_network_provisioned(tenant_id, network_id, segmentation_id=None,
segment_id=None):
"""Checks if a networks is already known to EOS
:returns: True, if yes; False otherwise.
:param tenant_id: globally unique neutron tenant identifier
:param network_id: globally unique neutron network identifier
:param segment_id: globally unique neutron network segment identifier
"""
session = db.get_reader_session()
with session.begin():
filters = {'tenant_id': tenant_id,
'network_id': network_id}
if segmentation_id:
filters['segmentation_id'] = segmentation_id
if segment_id:
filters['id'] = segment_id
num_nets = (session.query(db_models.AristaProvisionedNets).
filter_by(**filters).count())
return num_nets > 0
def is_tenant_provisioned(tenant_id):
"""Checks if a tenant is already known to EOS
:returns: True, if yes; False otherwise.
:param tenant_id: globally unique neutron tenant identifier
"""
session = db.get_reader_session()
with session.begin():
num_tenants = (session.query(db_models.AristaProvisionedTenants).
filter_by(tenant_id=tenant_id).count())
return num_tenants > 0
def num_nets_provisioned(tenant_id):
"""Returns number of networks for a given tennat.
:param tenant_id: globally unique neutron tenant identifier
"""
session = db.get_reader_session()
with session.begin():
return (session.query(db_models.AristaProvisionedNets).
filter_by(tenant_id=tenant_id).count())
def num_vms_provisioned(tenant_id):
"""Returns number of VMs for a given tennat.
:param tenant_id: globally unique neutron tenant identifier
"""
session = db.get_reader_session()
with session.begin():
return (session.query(db_models.AristaProvisionedVms).
filter_by(tenant_id=tenant_id).count())
def get_networks(tenant_id):
"""Returns all networks for a given tenant in EOS-compatible format.
See AristaRPCWrapper.get_network_list() for return value format.
:param tenant_id: globally unique neutron tenant identifier
"""
session = db.get_reader_session()
with session.begin():
model = db_models.AristaProvisionedNets
# hack for pep8 E711: comparison to None should be
# 'if cond is not None'
none = None
all_nets = []
if tenant_id != 'any':
all_nets = (session.query(model).
filter(model.tenant_id == tenant_id,
model.segmentation_id != none))
else:
all_nets = (session.query(model).
filter(model.segmentation_id != none))
res = dict(
(net.network_id, net.eos_network_representation(
VLAN_SEGMENTATION))
for net in all_nets
)
return res
def get_vms(tenant_id):
"""Returns all VMs for a given tenant in EOS-compatible format.
:param tenant_id: globally unique neutron tenant identifier
"""
session = db.get_reader_session()
with session.begin():
model = db_models.AristaProvisionedVms
# hack for pep8 E711: comparison to None should be
# 'if cond is not None'
none = None
all_ports = (session.query(model).
filter(model.tenant_id == tenant_id,
model.host_id != none,
model.vm_id != none,
model.network_id != none,
model.port_id != none))
ports = {}
for port in all_ports:
if port.port_id not in ports:
ports[port.port_id] = port.eos_port_representation()
else:
ports[port.port_id]['hosts'].append(port.host_id)
vm_dict = dict()
def eos_vm_representation(port):
return {u'vmId': port['deviceId'],
u'baremetal_instance': False,
u'ports': [port]}
for port in ports.values():
deviceId = port['deviceId']
if deviceId in vm_dict:
vm_dict[deviceId]['ports'].append(port)
else:
vm_dict[deviceId] = eos_vm_representation(port)
return vm_dict
def are_ports_attached_to_network(net_id):
"""Checks if a given network is used by any port, excluding dhcp port.
:param net_id: globally unique network ID
"""
session = db.get_reader_session()
with session.begin():
model = db_models.AristaProvisionedVms
return session.query(model).filter_by(network_id=net_id).filter(
~model.vm_id.startswith('dhcp')).count() > 0
def get_ports(tenant_id=None):
"""Returns all ports of VMs in EOS-compatible format.
:param tenant_id: globally unique neutron tenant identifier
"""
session = db.get_reader_session()
with session.begin():
model = db_models.AristaProvisionedVms
# hack for pep8 E711: comparison to None should be
# 'if cond is not None'
none = None
if tenant_id:
all_ports = (session.query(model).
filter(model.tenant_id == tenant_id,
model.host_id != none,
model.vm_id != none,
model.network_id != none,
model.port_id != none))
else:
all_ports = (session.query(model).
filter(model.tenant_id != none,
model.host_id != none,
model.vm_id != none,
model.network_id != none,
model.port_id != none))
ports = {}
for port in all_ports:
if port.port_id not in ports:
ports[port.port_id] = port.eos_port_representation()
ports[port.port_id]['hosts'].append(port.host_id)
return ports
def get_tenants():
"""Returns list of all tenants in EOS-compatible format."""
session = db.get_reader_session()
with session.begin():
model = db_models.AristaProvisionedTenants
all_tenants = session.query(model)
res = dict(
(tenant.tenant_id, tenant.eos_tenant_representation())
for tenant in all_tenants
)
return res
def _make_port_dict(record):
"""Make a dict from the BM profile DB record."""
return {'port_id': record.port_id,
'host_id': record.host,
'vnic_type': record.vnic_type,
'profile': record.profile}
def get_all_baremetal_ports():
"""Returns a list of all ports that belong to baremetal hosts."""
session = db.get_reader_session()
with session.begin():
querry = session.query(ml2_models.PortBinding)
bm_ports = querry.filter_by(vnic_type='baremetal').all()
return {bm_port.port_id: _make_port_dict(bm_port)
for bm_port in bm_ports}
def get_all_portbindings():
"""Returns a list of all ports bindings."""
session = db.get_reader_session()
with session.begin():
query = session.query(ml2_models.PortBinding)
ports = query.all()
return {port.port_id: _make_port_dict(port)
for port in ports}
def get_port_binding_level(filters):
"""Returns entries from PortBindingLevel based on the specified filters."""
session = db.get_reader_session()
with session.begin():
return (session.query(ml2_models.PortBindingLevel).
filter_by(**filters).
order_by(ml2_models.PortBindingLevel.level).
all())
def get_network_segments_by_port_id(port_id):
session = db.get_reader_session()
with session.begin():
segments = (session.query(segment_models.NetworkSegment,
ml2_models.PortBindingLevel).
join(ml2_models.PortBindingLevel).
filter_by(port_id=port_id).
order_by(ml2_models.PortBindingLevel.level).
all())
return [segment[0] for segment in segments]
def get_trunk_port_by_subport_id(subport_id):
"""Returns trunk parent port based on sub port id."""
session = db.get_reader_session()
with session.begin():
subport = (session.query(trunk_models.SubPort).
filter_by(port_id=subport_id).first())
if subport:
trunk_id = subport.trunk_id
return get_trunk_port_by_trunk_id(trunk_id)
def get_trunk_port_by_trunk_id(trunk_id):
session = db.get_reader_session()
with session.begin():
trunk_port = (session.query(trunk_models.Trunk).
filter_by(id=trunk_id).first())
if trunk_port:
return trunk_port.port
class NeutronNets(db_base_plugin_v2.NeutronDbPluginV2,
sec_db.SecurityGroupDbMixin):
"""Access to Neutron DB.
Provides access to the Neutron Data bases for all provisioned
networks as well ports. This data is used during the synchronization
of DB between ML2 Mechanism Driver and Arista EOS
Names of the networks and ports are not stroed in Arista repository
They are pulled from Neutron DB.
"""
def __init__(self):
self.admin_ctx = nctx.get_admin_context()
def get_network_name(self, tenant_id, network_id):
network = self._get_network(tenant_id, network_id)
network_name = None
if network:
network_name = network[0]['name']
return network_name
def get_all_networks_for_tenant(self, tenant_id):
filters = {'tenant_id': [tenant_id]}
return super(NeutronNets,
self).get_networks(self.admin_ctx, filters=filters) or []
def get_all_networks(self):
return super(NeutronNets, self).get_networks(self.admin_ctx) or []
def get_all_ports_for_tenant(self, tenant_id):
filters = {'tenant_id': [tenant_id]}
return super(NeutronNets,
self).get_ports(self.admin_ctx, filters=filters) or []
def get_all_ports(self):
return super(NeutronNets, self).get_ports(self.admin_ctx) or []
def get_shared_network_owner_id(self, network_id):
filters = {'id': [network_id]}
nets = self.get_networks(self.admin_ctx, filters=filters) or []
segments = segments_db.get_network_segments(self.admin_ctx,
network_id)
if not nets or not segments:
return
if (nets[0]['shared'] and
segments[0][driver_api.NETWORK_TYPE] == n_const.TYPE_VLAN):
return nets[0]['tenant_id']
def get_network_segments(self, network_id, dynamic=False, context=None):
context = context if context is not None else self.admin_ctx
segments = segments_db.get_network_segments(context, network_id,
filter_dynamic=dynamic)
if dynamic:
for segment in segments:
segment['is_dynamic'] = True
return segments
def get_all_network_segments(self, network_id, context=None):
segments = self.get_network_segments(network_id, context=context)
segments += self.get_network_segments(network_id, dynamic=True,
context=context)
return segments
def get_segment_by_id(self, context, segment_id):
return segments_db.get_segment_by_id(context,
segment_id)
def get_network_from_net_id(self, network_id, context=None):
filters = {'id': [network_id]}
ctxt = context if context else self.admin_ctx
return super(NeutronNets,
self).get_networks(ctxt, filters=filters) or []
def _get_network(self, tenant_id, network_id):
filters = {'tenant_id': [tenant_id],
'id': [network_id]}
return super(NeutronNets,
self).get_networks(self.admin_ctx, filters=filters) or []
def get_subnet_info(self, subnet_id):
return self.get_subnet(subnet_id)
def get_subnet_ip_version(self, subnet_id):
subnet = self.get_subnet(subnet_id)
return subnet['ip_version'] if 'ip_version' in subnet else None
def get_subnet_gateway_ip(self, subnet_id):
subnet = self.get_subnet(subnet_id)
return subnet['gateway_ip'] if 'gateway_ip' in subnet else None
def get_subnet_cidr(self, subnet_id):
subnet = self.get_subnet(subnet_id)
return subnet['cidr'] if 'cidr' in subnet else None
def get_network_id(self, subnet_id):
subnet = self.get_subnet(subnet_id)
return subnet['network_id'] if 'network_id' in subnet else None
def get_network_id_from_port_id(self, port_id):
port = self.get_port(port_id)
return port['network_id'] if 'network_id' in port else None
def get_subnet(self, subnet_id):
return super(NeutronNets,
self).get_subnet(self.admin_ctx, subnet_id) or {}
def get_port(self, port_id):
return super(NeutronNets,
self).get_port(self.admin_ctx, port_id) or {}
def get_all_security_gp_to_port_bindings(self):
return super(NeutronNets, self)._get_port_security_group_bindings(
self.admin_ctx) or []
def get_security_gp_to_port_bindings(self, sec_gp_id):
filters = {'security_group_id': [sec_gp_id]}
return super(NeutronNets, self)._get_port_security_group_bindings(
self.admin_ctx, filters=filters) or []
def get_security_group(self, sec_gp_id):
return super(NeutronNets,
self).get_security_group(self.admin_ctx, sec_gp_id) or []
def get_security_groups(self):
sgs = super(NeutronNets,
self).get_security_groups(self.admin_ctx) or []
sgs_all = {}
if sgs:
for s in sgs:
sgs_all[s['id']] = s
return sgs_all
def get_security_group_rule(self, sec_gpr_id):
return super(NeutronNets,
self).get_security_group_rule(self.admin_ctx,
sec_gpr_id) or []
def validate_network_rbac_policy_change(self, resource, event, trigger,
context, object_type, policy,
**kwargs):
return super(NeutronNets, self).validate_network_rbac_policy_change(
resource, event, trigger, context, object_type, policy, kwargs)
|