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
etc/murano
meta/io.murano.lib.networks.Neutron
muranoapi
common
db/services
engine/system

View File

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

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_hosts', default=250),
cfg.StrOpt('env_ip_template', default='10.0.0.0'),
cfg.StrOpt('default_dns', default='8.8.8.8')
]
stats_opt = [

View File

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

View File

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