From 86a3fa3abe8eb16c53dee3549a7e4a039be0ec22 Mon Sep 17 00:00:00 2001 From: Alexander Tivelkov Date: Tue, 29 Apr 2014 18:27:35 +0400 Subject: [PATCH] Added functionality to assign FloatingIP addresses The Instance class got an boolean field 'assignFloatingIp', false by default. If this is set 'true', the instance will attempt to assign a floating ip in one of its networks (starting from default ones) NetworkExplorer class got a functionality to dicover the ID of the external network: - for newly created networks it will use their specified external router's external_gateway_info - for existing networks it will iterate among all their routers Change-Id: I754cd41ffacbf2a2ec62ac23c3a5a7883d1e13b5 Closes-Bug: #1314193 --- .../Classes/NewNetwork.yaml | 32 +++++++++++++++++-- .../io.murano/Classes/resources/Instance.yaml | 16 ++++++++-- muranoapi/engine/system/net_explorer.py | 27 ++++++++++++++++ 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/meta/io.murano.lib.networks.Neutron/Classes/NewNetwork.yaml b/meta/io.murano.lib.networks.Neutron/Classes/NewNetwork.yaml index fdbdcf917..38dd0480d 100644 --- a/meta/io.murano.lib.networks.Neutron/Classes/NewNetwork.yaml +++ b/meta/io.murano.lib.networks.Neutron/Classes/NewNetwork.yaml @@ -51,6 +51,9 @@ Workflow: Arguments: - instance: Contract: $.class(res:Instance).notNull() + - assignFloatingIp: + Contract: $.bool().notNull() + Default: false Body: - $.ensureNetworkConfigured() - $portname: $instance.name + '-port-to-' + $.id() @@ -67,6 +70,33 @@ Workflow: - Ref: $portname - $.environment.stack.updateTemplate($template) + - If: $assignFloatingIp + Then: + - $extNetId: $.netExplorer.getExternalNetworkIdForRouter($.externalRouterId) + - If: $extNetId != null + Then: + - $fip_name: $instance.name + '-FloatingIP-' + $.id() + - $template: + Resources: + $fip_name: + Type: 'OS::Neutron::FloatingIP' + Properties: + floating_network_id: $extNetId + $instance.name + '-FloatingIpAssoc-' + $.id(): + Type: 'OS::Neutron::FloatingIPAssociation' + Properties: + floatingip_id: + Ref: $fip_name + port_id: + Ref: $portname + Outputs: + $instance.name + '-FloatingIPaddress': + Value: + Fn::GetAtt: + - $fip_name + - floating_ip_address + Description: Floating IP assigned + - $.environment.stack.updateTemplate($template) ensureNetworkConfigured: Body: @@ -127,5 +157,3 @@ Workflow: router_id: $.externalRouterId subnet_id: {Ref: $.subnet_res_name} - $.environment.stack.updateTemplate($template) - - diff --git a/meta/io.murano/Classes/resources/Instance.yaml b/meta/io.murano/Classes/resources/Instance.yaml index 761b99d44..66d401686 100644 --- a/meta/io.murano/Classes/resources/Instance.yaml +++ b/meta/io.murano/Classes/resources/Instance.yaml @@ -29,6 +29,12 @@ Properties: useEnvironmentNetwork: true useFlatNetwork: false customNetworks: [] + assignFloatingIp: + Contract: $.bool().notNull() + Default: false + floatingIpAddress: + Contract: $.string() + Usage: Out Workflow: initialize: @@ -64,7 +70,7 @@ Workflow: - $.environment.stack.push() - $outputs: $.environment.stack.output() - $.ipAddresses: $outputs.get(format('{0}-PublicIp', $this.name)) - + - $.floatingIpAddress: $outputs.get(format('{0}-FloatingIPaddress', $this.name)) - $.environment.instanceNotifier.trackApplication($this) joinNet: @@ -74,7 +80,13 @@ Workflow: Body: - If: $net != null Then: - $net.addHostToNetwork($) + - If: $.assignFloatingIp and (not bool($.getAttr(fipAssigned))) + Then: + - $assignFip: true + - $.setAttr(fipAssigned, true) + Else: + - $assignFip: false + - $net.addHostToNetwork($, $assignFip) destroy: Body: diff --git a/muranoapi/engine/system/net_explorer.py b/muranoapi/engine/system/net_explorer.py index d566130c8..996d82d65 100644 --- a/muranoapi/engine/system/net_explorer.py +++ b/muranoapi/engine/system/net_explorer.py @@ -102,6 +102,33 @@ class NetworkExplorer(murano_object.MuranoObject): def getDefaultDns(self): return self._settings.default_dns + # noinspection PyPep8Naming + def getExternalNetworkIdForRouter(self, routerId): + router = self._neutron.show_router(routerId).get('router') + if not router or 'external_gateway_info' not in router: + return None + return router['external_gateway_info'].get('network_id') + + # noinspection PyPep8Naming + def getExternalNetworkIdForNetwork(self, networkId): + network = self._neutron.show_network(networkId).get('network') + if network.get('router:external', False): + return networkId + + # Get router interfaces of the network + router_ports = self._neutron.list_ports( + **{'device_owner': 'network:router_interface', + 'network_id': networkId}).get('ports') + + # For each router this network is connected to + # check if the router has external_gateway set + for router_port in router_ports: + ext_net_id = self.getExternalNetworkIdForRouter( + router_port.get('device_id')) + if ext_net_id: + return ext_net_id + return None + def _get_cidrs_taken_by_router(self, router_id): if not router_id: return []