blob: 425d3eb302e4e6b133c03a0f7c6b97c185d577c3 [file] [log] [blame]
Scott Baker62c7eaf2018-05-22 15:59:26 -07001# Copyright 2017-present Open Networking Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15from synchronizers.new_base.pullstep import PullStep
16from synchronizers.new_base.modelaccessor import Network, Port, OpenStackService, OpenStackServiceInstance
17
18from xosconfig import Config
19from multistructlog import create_logger
20
21log = create_logger(Config().get('logging'))
22
23class OpenStackPortPullStep(PullStep):
24 def __init__(self):
25 super(OpenStackPortPullStep, self).__init__(observed_model=Port)
26
27 def connect_openstack_admin(self, service, required_version=None):
28 import openstack
29
30 if required_version:
31 if LooseVersion(openstack.version.__version__) < LooseVersion(required_version):
32 raise Exception("Insufficient OpenStack library version",
33 installed_version=openstack.version__version__,
34 required_version=required_version)
35
36 conn = openstack.connect(auth_url=service.auth_url,
37 project_name="admin",
38 username=service.admin_user,
39 password=service.admin_password,
40 user_domain_name="Default",
41 project_domain_name="Default")
42 return conn
43
44 def pull_records(self):
45 service = OpenStackService.objects.first() # TODO(smbaker): Fix, hardcoded
46 conn = self.connect_openstack_admin(service)
47
48 ports = Port.objects.all()
49 ports_by_id = {}
50 ports_by_neutron_port = {}
51 for port in ports:
52 ports_by_id[port.id] = port
53 ports_by_neutron_port[port.port_id] = port
54
55 networks = Network.objects.all()
56 networks_by_id = {}
57 for network in networks:
58 for nd in network.controllernetworks.all():
59 networks_by_id[nd.net_id] = network
60
61 os_instances = OpenStackServiceInstance.objects.all()
62 os_instances_by_handle = {}
63 for instance in os_instances:
64 if instance.backend_handle:
65 os_instances_by_handle[instance.backend_handle] = instance
66
67 os_ports = list(conn.network.ports())
68 for os_port in os_ports:
69 if os_port.id in ports_by_neutron_port:
70 # we already have it
71 continue
72 if os_port.device_id not in os_instances_by_handle:
73 # it's not one of ours
74 log.info("No instance for port", os_port=os_port)
75 continue
76 if os_port.network_id not in networks_by_id:
77 # there's no network for it
78 log.info("No network for port", os_port=os_port)
79 continue
80 if not os_port.fixed_ips:
81 # there's no ip address
82 log.info("No ip for port", os_port=os_port)
83 continue
84 network = networks_by_id[os_port.network_id]
85 instance = os_instances_by_handle[os_port.device_id]
86 ip = os_port.fixed_ips[0]["ip_address"]
87 mac = os_port.mac_address
88 port = Port(network=network,
89 instance=None, # TODO(smbaker): link to openstack instance
90 ip=ip,
91 mac=mac,
92 port_id=os_port.id)
93 port.save()
94 log.info("Created port", port=port, os_port=os_port)