From b7c2aac9a2b7eec5551589586a3ec59b7f2df820 Mon Sep 17 00:00:00 2001 From: Alexander Tivelkov Date: Mon, 28 Apr 2014 18:05:13 +0400 Subject: [PATCH] Implemented AdvNetworking scenarios via Neutron Added a new package ( io.murano.lib.networks.Neutron) to handle networking via Neutron The package introduces a class 'NewNetwork' (io.murano.lib.networks.neutron.NewNetwork) This class is capable of the following: - Create a new Network (L2 segment) - Use NetworkExplorer class to allocate an available CIDR - Create a new Subnet (L3 segment) in the created Network with the allocated CIDR - Use NetworkExplorer class to locate an available router - Use NetworkExplorer class to detect the default DNS nameserver - Uplink the created subnet to the located router Also, as this class extends io.murano.resources.Network, it implements the addHostToNetwork method The implementation creates a Neutron Port and connects that port to a created network and intance This commit also modifies the environment-creation logic of the API, allowing to add default networks to the Environment object. This is a temporary solution: in future the instantiation of this object(s) should be done in MuranoPL This commit concludes the minimum set of functionality needed to implement AdvancedNetworking in 0.4.x feature set. Closes-bug: #1308921 Change-Id: I885620099995b0d402a23def3ff428fb902973d2 --- etc/murano/murano-api.conf.sample | 3 + .../Classes/NewNetwork.yaml | 131 ++++++++++++++++++ .../manifest.yaml | 10 ++ muranoapi/common/config.py | 1 + muranoapi/db/services/environments.py | 28 ++++ muranoapi/engine/system/net_explorer.py | 4 + 6 files changed, 177 insertions(+) create mode 100644 meta/io.murano.lib.networks.Neutron/Classes/NewNetwork.yaml create mode 100644 meta/io.murano.lib.networks.Neutron/manifest.yaml diff --git a/etc/murano/murano-api.conf.sample b/etc/murano/murano-api.conf.sample index 7589801b..9ab081e7 100644 --- a/etc/murano/murano-api.conf.sample +++ b/etc/murano/murano-api.conf.sample @@ -169,3 +169,6 @@ max_hosts = 250 # Template IP address for generating environment subnet cidrs env_ip_template = 10.0.0.0 + +# Default DNS nameserver to be assigned to created Networks +default_dns = 8.8.8.8 diff --git a/meta/io.murano.lib.networks.Neutron/Classes/NewNetwork.yaml b/meta/io.murano.lib.networks.Neutron/Classes/NewNetwork.yaml new file mode 100644 index 00000000..fdbdcf91 --- /dev/null +++ b/meta/io.murano.lib.networks.Neutron/Classes/NewNetwork.yaml @@ -0,0 +1,131 @@ +Namespaces: + =: io.murano.lib.networks.neutron + res: io.murano.resources + std: io.murano + sys: io.murano.system + +Name: NewNetwork + +Extends: res:Network + +Properties: + name: + Contract: $.string().notNull() + + externalRouterId: + Contract: $.string() + Usage: InOut + + autoUplink: + Contract: $.bool().notNull() + Default: true + + autogenerateSubnet: + Contract: $.bool().notNull() + Default: true + + subnetCidr: + Contract: $.string() + Usage: InOut + + dnsNameserver: + Contract: $.string() + Usage: InOut + + useDefaultDns: + Contract: $.bool().notNull() + Default: true + +Workflow: + initialize: + Body: + - $.environment: $.find(std:Environment).require() + - $.netExplorer: new(sys:NetworkExplorer) + + deploy: + Body: + - $.ensureNetworkConfigured() + - $.environment.instanceNotifier.untrackApplication($this) + + addHostToNetwork: + Arguments: + - instance: + Contract: $.class(res:Instance).notNull() + Body: + - $.ensureNetworkConfigured() + - $portname: $instance.name + '-port-to-' + $.id() + - $template: + Resources: + $portname: + Type: 'OS::Neutron::Port' + Properties: + network_id: {Ref: $.net_res_name} + fixed_ips: [{subnet_id: {Ref: $.subnet_res_name}}] + $instance.name: + Properties: + NetworkInterfaces: + - Ref: $portname + - $.environment.stack.updateTemplate($template) + + + ensureNetworkConfigured: + Body: + - If: !yaql "not bool($.getAttr(networkConfigured))" + Then: + - If: $.useDefaultDns and (not bool($.dnsNameserver)) + Then: + - $.dnsNameserver: $.netExplorer.getDefaultDns() + + - $.net_res_name: $.name + '-net-' + $.id() + - $.subnet_res_name: $.name + '-subnet-' + $.id() + - $.createNetwork() + - If: $.autoUplink and (not bool($.externalRouterId)) + Then: + - $.externalRouterId: $.netExplorer.getDefaultRouter() + - If: $.autogenerateSubnet and (not bool($.subnetCidr)) + Then: + - $.subnetCidr: $.netExplorer.getAvailableCidr($.externalRouterId, $.id()) + - $.createSubnet() + - If: !yaql "bool($.externalRouterId)" + Then: + - $.createRouterInterface() + + - $.environment.stack.push() + - $.setAttr(networkConfigured, true) + + + createNetwork: + Body: + - $template: + Resources: + $.net_res_name: + Type: 'OS::Neutron::Net' + Properties: + name: $.name + - $.environment.stack.updateTemplate($template) + + createSubnet: + Body: + - $template: + Resources: + $.subnet_res_name: + Type: 'OS::Neutron::Subnet' + Properties: + network_id: {Ref: $.net_res_name} + ip_version: 4 + dns_nameservers: [$.dnsNameserver] + cidr: $.subnetCidr + - $.environment.stack.updateTemplate($template) + + createRouterInterface: + Body: + - $template: + Resources: + $.name + '-ri-' + $.id(): + Type: 'OS::Neutron::RouterInterface' + Properties: + router_id: $.externalRouterId + subnet_id: {Ref: $.subnet_res_name} + - $.environment.stack.updateTemplate($template) + + diff --git a/meta/io.murano.lib.networks.Neutron/manifest.yaml b/meta/io.murano.lib.networks.Neutron/manifest.yaml new file mode 100644 index 00000000..79e0f411 --- /dev/null +++ b/meta/io.murano.lib.networks.Neutron/manifest.yaml @@ -0,0 +1,10 @@ +Format: 1.0 +Type: Library +FullName: io.murano.lib.networks.Neutron +Name: Neutron Networking library +Description: | + A library defining various classes to create and manage networking resources via Neutron +Author: 'Mirantis, Inc' +Tags: [Networking, Neutron] +Classes: + io.murano.lib.networks.neutron.NewNetwork: NewNetwork.yaml diff --git a/muranoapi/common/config.py b/muranoapi/common/config.py index 2af1d9bd..34ba0e62 100644 --- a/muranoapi/common/config.py +++ b/muranoapi/common/config.py @@ -91,6 +91,7 @@ networking_opts = [ cfg.IntOpt('max_environments', default=20), cfg.IntOpt('max_hosts', default=250), cfg.StrOpt('env_ip_template', default='10.0.0.0'), + cfg.StrOpt('default_dns', default='8.8.8.8') ] stats_opt = [ diff --git a/muranoapi/db/services/environments.py b/muranoapi/db/services/environments.py index a76737f2..c4a4dd3a 100644 --- a/muranoapi/db/services/environments.py +++ b/muranoapi/db/services/environments.py @@ -16,6 +16,7 @@ import collections from muranoapi.common import rpc from muranoapi.common import uuidutils + from muranoapi.db import models from muranoapi.db.services import sessions from muranoapi.db import session as db_session @@ -27,6 +28,11 @@ EnvironmentStatus = collections.namedtuple('EnvironmentStatus', [ ready='ready', pending='pending', deploying='deploying' ) +DEFAULT_NETWORKS = { + 'environment': 'io.murano.lib.networks.neutron.NewNetwork', + # 'flat': 'io.murano.lib.networks.ExistingNetworkConnector' +} + class EnvironmentServices(object): @staticmethod @@ -88,6 +94,8 @@ class EnvironmentServices(object): 'id': uuidutils.generate_uuid(), }} objects.update(environment_params) + objects.update( + EnvironmentServices.generate_default_networks(objects['name'])) objects['?']['type'] = 'io.murano.Environment' environment_params['tenant_id'] = tenant_id @@ -192,3 +200,23 @@ class EnvironmentServices(object): else: session.description = environment session.save(unit) + + @staticmethod + def generate_default_networks(env_name): + # TODO(ativelkov): + # This is a temporary workaround. Need to find a better way: + # These objects have to be created in runtime when the environment is + # deployed for the first time. Currently there is no way to persist + # such changes, so we have to create the objects on the API side + return { + 'defaultNetworks': { + 'environment': { + '?': { + 'id': uuidutils.generate_uuid(), + 'type': DEFAULT_NETWORKS['environment'] + }, + 'name': env_name + '-network' + }, + 'flat': None + } + } diff --git a/muranoapi/engine/system/net_explorer.py b/muranoapi/engine/system/net_explorer.py index d2fa778d..d566130c 100644 --- a/muranoapi/engine/system/net_explorer.py +++ b/muranoapi/engine/system/net_explorer.py @@ -98,6 +98,10 @@ class NetworkExplorer(murano_object.MuranoObject): return str(cidr) return None + # noinspection PyPep8Naming + def getDefaultDns(self): + return self._settings.default_dns + def _get_cidrs_taken_by_router(self, router_id): if not router_id: return []