Network Module - IP Address Management

Add new functionality to manage fixed and floating IPs

Change-Id: I821093a0cbee6c09823fa283b913f4a804400627
This commit is contained in:
kelepirci 2016-09-15 21:39:53 +03:00
parent 86628b054e
commit 858b094f32
9 changed files with 544 additions and 93 deletions

View File

@ -0,0 +1,20 @@
from flask_wtf import Form
from flask import flash
from wtforms import StringField, PasswordField, BooleanField, SubmitField, \
ValidationError, SelectField
from wtforms.validators import Required, Length, Email, Regexp, EqualTo, \
IPAddress
from ..models import User, Role, Provider
from flask_login import login_user, logout_user, login_required, \
current_user
from keystoneauth1 import identity
from keystoneauth1 import session
from neutronclient.v2_0 import client
from novaclient import client as client_nova
class AssignFloatingIP(Form):
floatingip = StringField('Floating IP', validators=[Required(), Length(1, 128),
IPAddress()])
server = SelectField('Server', choices = [])

View File

@ -1,8 +1,9 @@
import datetime, requests, json, string, random
import datetime, requests, json, string, random, pprint
from keystoneauth1 import identity
from keystoneauth1 import session
from neutronclient.v2_0 import client
from novaclient import client as client_nova
from flask import render_template, redirect, request, url_for, flash
@ -10,6 +11,8 @@ from flask_login import login_user, logout_user, login_required, \
current_user
from flask_principal import Identity, AnonymousIdentity, \
identity_changed
from .forms import AssignFloatingIP
from . import network
from .. import db
@ -36,10 +39,10 @@ def print_values(val, type):
def index():
return render_template('network/index.html')
@network.route('/list-networks', methods=['GET', 'POST'])
@network.route('/list-ips', methods=['GET', 'POST'])
@login_required
@requires_roles("user","admin")
def list_networks():
def list_ips():
user = User.query.get_or_404(current_user.id)
provider = Provider.query.get_or_404("1")
auth = identity.Password(auth_url=provider.url,
@ -50,12 +53,70 @@ def list_networks():
user_domain_name='Default')
sess = session.Session(auth=auth)
neutron = client.Client(session=sess)
nova = client_nova.Client('2', session=sess)
networks = neutron.list_networks()
subnets = neutron.list_subnets()
routers = neutron.list_routers()
return render_template('network/list_networks.html',
floatingips = neutron.list_floatingips()
ports = neutron.list_ports()
return render_template('network/list_ips.html',
title="List Networks",
block_description = "manage all of your networks",
user=user, provider=provider,neutron=neutron,
user=user, provider=provider,neutron=neutron,nova=nova,
networks=networks,subnets=subnets,routers=routers,
floatingips=floatingips, ports=ports,
sess=sess)
@network.route('/assign-floatingip/<id>', methods=['GET', 'POST'])
@login_required
@requires_roles("user","admin")
def assign_floatingip(id):
user = User.query.get_or_404(current_user.id)
provider = Provider.query.get_or_404("1")
form = AssignFloatingIP()
auth = identity.Password(auth_url=provider.url,
username=user.username,
password=user.provider_password,
project_name=user.username,
project_domain_name='Default',
user_domain_name='Default')
sess = session.Session(auth=auth)
neutron = client.Client(session=sess)
nova = client_nova.Client('2', session=sess)
servers = nova.servers.list()
networks = neutron.list_networks()
subnets = neutron.list_subnets()
routers = neutron.list_routers()
floatingip = neutron.list_floatingips(id=id)
ports = neutron.list_ports()
return render_template('network/assign_floatingip.html',
title="Assign Floating IP",
block_description = "assign floating ip to server",
user=user, provider=provider,neutron=neutron,nova=nova,
networks=networks,subnets=subnets,routers=routers,
floatingip=floatingip, ports=ports,form=form,
servers=servers,
sess=sess)
@network.route('/edit-subnet/<id>', methods=['GET', 'POST'])
@login_required
@requires_roles("admin")
def edit_subnet(id):
user = User.query.get_or_404(current_user.id)
provider = Provider.query.get_or_404("1")
auth = identity.Password(auth_url=provider.url,
username=user.username,
password=user.provider_password,
project_name=user.username,
project_domain_name='Default',
user_domain_name='Default')
sess = session.Session(auth=auth)
neutron = client.Client(session=sess)
nova = client_nova.Client('2', session=sess)
subnet = neutron.list_subnets(id=id)
ports = neutron.list_ports(subnet_id=id)
return render_template('network/edit_subnet.html',
title="Edit Subnet",
block_description = "edit and look subnet details",
subnet=subnet,neutron=neutron,ports=ports,nova=nova,
sess=sess)

View File

@ -38,8 +38,10 @@ def list_servers():
sess = session.Session(auth=auth)
nova = client.Client('2', session=sess)
servers = nova.servers.list()
for_servers = [(server.id, server.name)
for server in nova.servers.list()]
return render_template('server/list_servers.html',
title="List Servers",
block_description = "list your servers",
user=user, provider=provider,nova=nova,
servers=servers)
servers=servers,for_servers=for_servers)

View File

@ -0,0 +1,82 @@
{% extends "adminlte/base.html" %}
{% import "adminlte/layout.html" as layout with context %}
{% import "adminlte/widgets.html" as widgets with context %}
{% block title %}Network - {{ title }}{% endblock %}
{% block description %}{{ block_description }}{% endblock %}
{% block navbar %}
{% include "navbar.html" %}
{%- endblock navbar %}
{% block sidebar -%}
{% include 'sidebar.html' %}
{% include 'sidebar_menu.html' %}
{%- endblock sidebar %}
{% block content_header -%}
{% include 'network/content_header.html' %}
{%- endblock content_header %}
{% block content -%}
<!--{{ subnets }}<hr />
{{ networks }} <hr />
{{ ports }}
-->
<!-- Main content -->
<div class="row">
<form class="form-horizontal" action="" method="post">
{{ form.hidden_tag() }}
<input type="hidden" name="floatingip" value="{{ floatingip.floatingips[0].floating_ip_address }}">
<div class="col-xs-4">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Floating IP Address</h3>
</div>
<div class="box-body">
<h3>
{{ floatingip.floatingips[0].floating_ip_address }}
</h3>
</div>
</div>
</div>
<div class="col-xs-4">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Server</h3>
</div>
<div class="box-body">
<select name="server" class="form-control">
{% for server in servers %}
<option value="{{ server.id }}">{{ server.name }}</option>
{% endfor %}
</select>
{% if form.server.errors %}
<br />
<span class="text-red">{% for error in form.server.errors %} {{ error }} {% endfor %}</span>
{% endif %}
</div>
</div>
</div>
<div class="col-xs-4">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Action</h3>
</div>
<div class="box-body">
<button type="submit" name="submit" class="btn btn-primary btn-block btn-flat" value="reassign">Reassign</button>
</div>
</div>
</div>
</form>
</div>
<!-- /.row -->
{%- endblock content %}

View File

@ -0,0 +1,207 @@
{% extends "adminlte/base.html" %}
{% import "adminlte/layout.html" as layout with context %}
{% import "adminlte/widgets.html" as widgets with context %}
{% block title %}Network - {{ title }}{% endblock %}
{% block description %}{{ block_description }}{% endblock %}
{% block navbar %}
{% include "navbar.html" %}
{%- endblock navbar %}
{% block sidebar -%}
{% include 'sidebar.html' %}
{% include 'sidebar_menu.html' %}
{%- endblock sidebar %}
{% block content_header -%}
{% include 'network/content_header.html' %}
{%- endblock content_header %}
{% block content -%}
<!-- Main content -->
{{ subnet }}
<div class="row">
<div class="col-xs-9">
</div>
<div class="col-xs-3">
<div style="margin-bottom:10px;" class="btn-group">
<button type="button" class="btn btn-primary">Edit</button>
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Edit</a></li>
<li class="divider"></li>
<li><a href="#">Delete</a></li>
</ul>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-3">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Name</h3>
</div>
<div class="box-body">
<h3> {{ subnet.subnets[0]['name'] }} </h3>
</div>
</div>
</div>
<div class="col-xs-3">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Network</h3>
</div>
<div class="box-body">
<h3> {{ neutron.list_networks(id=subnet.subnets[0]['network_id']).networks[0]['name']}} </h3>
</div>
</div>
</div>
<div class="col-xs-3">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">CIDR</h3>
</div>
<div class="box-body">
<h3> {{ subnet.subnets[0]['cidr'] }} </h3>
</div>
</div>
</div>
<div class="col-xs-3">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">IP Range</h3>
</div>
<div class="box-body">
<h3>
{{ subnet.subnets[0].allocation_pools[0]['start'] }} -
{{ subnet.subnets[0].allocation_pools[0]['end'] }}
</h3>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-3">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">DHCP</h3>
</div>
<div class="box-body">
<h3>
{% if subnet.subnets[0]['enable_dhcp'] %}
Enabled
{% else %}
Disabled
{% endif %}
</h3>
</div>
</div>
</div>
<div class="col-xs-3">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">Gateway</h3>
</div>
<div class="box-body">
<h3> {{ subnet.subnets[0]['gateway_ip']}} </h3>
</div>
</div>
</div>
<div class="col-xs-3">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">DNS Nameservers</h3>
</div>
<div class="box-body">
<h3>
{% for ns in subnet.subnets[0]['dns_nameservers'] %}
{{ ns }}
{% endfor %}
</h3>
</div>
</div>
</div>
<div class="col-xs-3">
<div class="box box-solid">
<div class="box-header with-border">
<h3 class="box-title">IP Version</h3>
</div>
<div class="box-body">
<h3>
IPv{{ subnet.subnets[0].ip_version }}
</h3>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">Subnet Ips</h3>
</div>
<div class="box-body">
<table id="example2" class="table table-bordered table-hover">
<thead>
<tr>
<th>IP Address</th>
<th>Attached</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{% for port in ports.ports %}
{% if port.fixed_ips[0]['subnet_id'] == subnet.subnets[0]['id'] %}
<tr>
<td> {{ port.fixed_ips[0]['ip_address'] }} </td>
<td>
{% set device_owner = port.device_owner.split(':') %}
{% if device_owner[0] == "compute" %}
{{ nova.servers.get(neutron.list_ports(id=port['id']).ports[0]['device_id']).name }}
{% else %}
{{ device_owner[0] }} : {{ device_owner[1] }}
{% endif %}
</td>
<td> {{ port['status'] }} </td>
<td>
<a href="#">Edit</a>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
<tfoot>
<tr>
<th>IP Address</th>
<th>Attached</th>
<th>Status</th>
<th>Action</th>
</tr>
</tfoot>
</table>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
</div>
<!-- /.col -->
</div>
<!-- /.row -->
{%- endblock content %}

View File

@ -0,0 +1,160 @@
{% extends "adminlte/base.html" %}
{% import "adminlte/layout.html" as layout with context %}
{% import "adminlte/widgets.html" as widgets with context %}
{% block title %}Network - {{ title }}{% endblock %}
{% block description %}{{ block_description }}{% endblock %}
{% block navbar %}
{% include "navbar.html" %}
{%- endblock navbar %}
{% block sidebar -%}
{% include 'sidebar.html' %}
{% include 'sidebar_menu.html' %}
{%- endblock sidebar %}
{% block content_header -%}
{% include 'network/content_header.html' %}
{%- endblock content_header %}
{% block content -%}
<!--{{ subnets }}<hr />
{{ networks }} <hr />
{{ ports }}
-->
<!-- Main content -->
<div class="row">
<div class="col-xs-12">
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">Floating IPs</h3>
</div>
<div class="box-body">
<table id="example2" class="table table-bordered table-hover">
<thead>
<tr>
<th>IP Address</th>
<th>Server</th>
<th>Mapped Private IP</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{% for floatingip in floatingips.floatingips %}
{% if floatingip['tenant_id'] == sess.get_project_id() %}
<tr>
<td>{{ floatingip['floating_ip_address'] }} </td>
<td>
{% if floatingip['port_id'] %}
{{ nova.servers.get(neutron.list_ports(id=floatingip['port_id']).ports[0]['device_id']).name }}
{% endif %}
</td>
<td>
{% if floatingip['port_id'] %}
{{ floatingip['fixed_ip_address'] }}
{% endif %}
</td>
<td> {{ floatingip['status'] }} </td>
<td>
<div style="margin-bottom:10px;" class="btn-group">
<button type="button" class="btn btn-default">
<a style="color:black" href="">Action</a>
</button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="{{ url_for('network.assign_floatingip', id=floatingip['id']) }}">Reassign</a></li>
<li><a href="">Unassign</a></li>
<li class="divider"></li>
<li><a style="color:red" href="#">Release</a></li>
</ul>
</div>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
<tfoot>
<tr>
<th>IP Address</th>
<th>Server</th>
<th>Mapped Private IP</th>
<th>Status</th>
<th>Action</th>
</tr>
</tfoot>
</table>
</div>
<!-- /.box-body -->
</div>
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">Private Subnets</h3>
</div>
<div class="box-body">
<table id="example2" class="table table-bordered table-hover">
<thead>
<tr>
<th>Name</th>
<th>Subnet</th>
<th>Network</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{% for subnet in subnets.subnets %}
{% if subnet['tenant_id'] == sess.get_project_id() %}
<tr>
<td> {{ subnet['name'] }} </td>
<td> {{ subnet['cidr'] }} </td>
<td> {{ neutron.list_networks(id=subnet['network_id']).networks[0].name }} </td>
<td>
<div style="margin-bottom:10px;" class="btn-group">
<button type="button" class="btn btn-default">
<a style="color:black" href="{{ url_for('network.edit_subnet', id=subnet['id']) }}">Edit</a>
</button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a href="{{ url_for('network.edit_subnet', id=subnet['id']) }}">Edit</a></li>
<li class="divider"></li>
<li><a style="color:red" href="#">Delete</a></li>
</ul>
</div>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
<tfoot>
<tr>
<th>Name</th>
<th>Subnet</th>
<th>Network</th>
<th>Action</th>
</tr>
</tfoot>
</table>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
</div>
<!-- /.col -->
</div>
<!-- /.row -->
{%- endblock content %}

View File

@ -1,83 +0,0 @@
{% extends "adminlte/base.html" %}
{% import "adminlte/layout.html" as layout with context %}
{% import "adminlte/widgets.html" as widgets with context %}
{% block title %}Server - {{ title }}{% endblock %}
{% block description %}{{ block_description }}{% endblock %}
{% block navbar %}
{% include "navbar.html" %}
{%- endblock navbar %}
{% block sidebar -%}
{% include 'sidebar.html' %}
{% include 'sidebar_menu.html' %}
{%- endblock sidebar %}
{% block content_header -%}
{% include 'server/content_header.html' %}
{%- endblock content_header %}
{% block content -%}
<!-- Main content -->
<div class="row">
<div class="col-xs-12">
<div class="box">
<div class="box-body">
<table id="example2" class="table table-bordered table-hover">
<thead>
<tr>
<th>Network Name</th>
<th>Subnets</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{% for network in networks.networks %}
<tr>
{% if network['tenant_id'] == sess.get_project_id() %}
<td>{{ network['name'] }}</td>
<td>
{% for subnet in network['subnets'] %}
{{ neutron.list_subnets(subnet).subnets[loop.index0]['name'] }} |
{{ neutron.list_subnets(subnet).subnets[loop.index0]['cidr'] }}
<br />
{% endfor %}
</td>
<td>{{ network['status'] }}</td>
<td>
<a href="{{ url_for('admin.edit_user_admin', id=user.id) }}">Edit</a>
|
<a href="{{ url_for('admin.delete_user_admin', id=user.id) }}">Delete</a>
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<th>Network Name</th>
<th>Subnets</th>
<th>Status</th>
<th>Action</th>
</tr>
</tfoot>
</table>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
</div>
<!-- /.col -->
</div>
<!-- /.row -->
{%- endblock content %}

View File

@ -26,7 +26,9 @@
{%- endblock content_header %}
{% block content -%}
<!-- Main content -->
<!-- Main content -->
{{ servers }} <hr />
{{ for_servers }} <hr />
<div class="row">
<div class="col-xs-12">
<div class="box">
@ -45,7 +47,7 @@
<tbody>
{% for server in servers %}
<tr>
<td>{{ server.name }}</td>
<td>{{ server.name }} - {{ server.id }} </td>
<td>
{% for ips in server.networks['private'] %}
{{ ips }} |

View File

@ -76,9 +76,9 @@
</a>
</li>
<li>
<a href="{{ url_for('network.index') }}">
<a href="{{ url_for('network.list_ips') }}">
<i class="fa fa-list"></i>
List Network
List IPs
</a>
</li>
</ul>