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
This commit is contained in:
Alexander Tivelkov 2014-04-28 18:05:13 +04:00
parent b7aec89493
commit b7c2aac9a2
6 changed files with 177 additions and 0 deletions

View File

@ -169,3 +169,6 @@ max_hosts = 250
# Template IP address for generating environment subnet cidrs # Template IP address for generating environment subnet cidrs
env_ip_template = 10.0.0.0 env_ip_template = 10.0.0.0
# Default DNS nameserver to be assigned to created Networks
default_dns = 8.8.8.8

View File

@ -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)

View File

@ -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

View File

@ -91,6 +91,7 @@ networking_opts = [
cfg.IntOpt('max_environments', default=20), cfg.IntOpt('max_environments', default=20),
cfg.IntOpt('max_hosts', default=250), cfg.IntOpt('max_hosts', default=250),
cfg.StrOpt('env_ip_template', default='10.0.0.0'), cfg.StrOpt('env_ip_template', default='10.0.0.0'),
cfg.StrOpt('default_dns', default='8.8.8.8')
] ]
stats_opt = [ stats_opt = [

View File

@ -16,6 +16,7 @@ import collections
from muranoapi.common import rpc from muranoapi.common import rpc
from muranoapi.common import uuidutils from muranoapi.common import uuidutils
from muranoapi.db import models from muranoapi.db import models
from muranoapi.db.services import sessions from muranoapi.db.services import sessions
from muranoapi.db import session as db_session from muranoapi.db import session as db_session
@ -27,6 +28,11 @@ EnvironmentStatus = collections.namedtuple('EnvironmentStatus', [
ready='ready', pending='pending', deploying='deploying' ready='ready', pending='pending', deploying='deploying'
) )
DEFAULT_NETWORKS = {
'environment': 'io.murano.lib.networks.neutron.NewNetwork',
# 'flat': 'io.murano.lib.networks.ExistingNetworkConnector'
}
class EnvironmentServices(object): class EnvironmentServices(object):
@staticmethod @staticmethod
@ -88,6 +94,8 @@ class EnvironmentServices(object):
'id': uuidutils.generate_uuid(), 'id': uuidutils.generate_uuid(),
}} }}
objects.update(environment_params) objects.update(environment_params)
objects.update(
EnvironmentServices.generate_default_networks(objects['name']))
objects['?']['type'] = 'io.murano.Environment' objects['?']['type'] = 'io.murano.Environment'
environment_params['tenant_id'] = tenant_id environment_params['tenant_id'] = tenant_id
@ -192,3 +200,23 @@ class EnvironmentServices(object):
else: else:
session.description = environment session.description = environment
session.save(unit) 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
}
}

View File

@ -98,6 +98,10 @@ class NetworkExplorer(murano_object.MuranoObject):
return str(cidr) return str(cidr)
return None return None
# noinspection PyPep8Naming
def getDefaultDns(self):
return self._settings.default_dns
def _get_cidrs_taken_by_router(self, router_id): def _get_cidrs_taken_by_router(self, router_id):
if not router_id: if not router_id:
return [] return []