Commit 02238427 by Szabolcs Gelencser

Add public IP display, associate operation

parent 7a0b9b2b
...@@ -1005,6 +1005,27 @@ class VmPortAddForm(OperationForm): ...@@ -1005,6 +1005,27 @@ class VmPortAddForm(OperationForm):
) )
return helper return helper
class VmPublicIpAddForm(OperationForm):
def __init__(self, *args, **kwargs):
pools = kwargs.pop('pools')
port_id = kwargs.pop('port_id')
poolsDict = (
(pool.id, pool.name,) for pool in pools
)
super(VmPublicIpAddForm, self).__init__(*args, **kwargs)
self.fields['pool'] = forms.ChoiceField(poolsDict, required=True, label=_('Pool'))
self.fields['port_id'] = forms.CharField(widget=forms.HiddenInput(), initial=port_id)
@property
def helper(self):
helper = super(VmPublicIpAddForm, self).helper
helper.layout = Layout(
Field("pool"),
Field("port_id"),
)
return helper
class CircleAuthenticationForm(AuthenticationForm): class CircleAuthenticationForm(AuthenticationForm):
# fields: username, password # fields: username, password
......
...@@ -48,95 +48,116 @@ ...@@ -48,95 +48,116 @@
{# </dd>#} {# </dd>#}
</dl> </dl>
</div> </div>
{% if i.host %} {% if i.internet_access %}
<div class="col-md-7"> <div class="col-md-7">
<ul class="nav nav-pills pull-right"> <span class="pull-right">
<li class="active"><a href="#ipv4_{{ i.host.vlan.pk }}" data-toggle="pill" class="text-center">{% trans "IPv4" %}</a></li> {% if i.public_ip %}
<li><a href="#ipv6_{{ i.host.vlan.pk }}" data-toggle="pill" class="text-center">{% trans "IPv6" %}</a></li> <dl>
</ul> <dt>{% trans "Public IP address" %}:</dt>
<h4>{% trans "Port access" %}</h4> <dd>{{ i.public_ip }}</dd>
<div class="tab-content" style="padding-top: 10px;"> </dl>
<div class="tab-pane active" id="ipv4_{{ i.host.vlan.pk }}">
<table class="table table-striped rule-table">
<thead>
<tr><th>
<i class="fa fa-globe fa-2x"></i>
<i class="fa fa-long-arrow-right fa-2x"></i>
</th><th>
<i class="fa fa-shield fa-2x"></i>
</th><th colspan="2">
<i class="fa fa-long-arrow-right fa-2x"></i>
<i class="fa fa-desktop fa-2x"></i>
</th></tr>
</thead>
<tbody>
{% for l in i.host.list_ports %}
{% if l.ipv4 %}
<tr>
<td>
{% display_portforward4 l %}
</td>
<td><i class="fa fa-long-arrow-right"></i></td>
<td>
{{ l.private }}/{{ l.proto }}
</td>
<td>
<span class="operation-wrapper">
<a href="{{ op.remove_port.get_url }}?rule={{ l.ipv4.pk }}"
class="btn btn-link btn-xs operation"
title="{% trans "Remove" %}"
{% if not op.remove_port %}disabled{% endif %}>
<i class="fa fa-times"><span class="sr-only">{% trans "Remove" %}</span></i>
</a>
</span>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div> <!-- /ipv4 -->
<div class="tab-pane" id="ipv6_{{ i.host.vlan.pk }}">
{% if i.host.ipv6 %}
<table class="table table-striped rule-table">
<thead>
<tr><th>
<i class="fa fa-globe fa-2x"></i>
</th><th>
<i class="fa fa-long-arrow-right fa-2x"></i>
</th><th colspan="2">
<i class="fa fa-desktop fa-2x"></i>
</th></tr>
</thead>
<tbody>
{% for l in i.host.list_ports %}
{% if l.ipv6 %}
<tr>
<td>
{% display_portforward6 l %}
</td>
<td><i class="fa fa-long-arrow-right"></i></td>
<td>
{{ l.private }}/{{ l.proto }}
</td>
<td>
<a href="{{ op.remove_port.get_url }}?rule={{ l.ipv4.pk }}" class="btn btn-link btn-xs vm-details-remove-port" data-rule="{{ l.ipv6.pk }}" title="{% trans "Remove" %}" {% if not op.remove_port %}disabled{% endif %}>
<i class="fa fa-times"><span class="sr-only">{% trans "Remove" %}</span></i>
</a>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
{% else %} {% else %}
<h4>{% trans "This VM doesn't have an IPv6 address!" %}</h4> {% with op=op.add_public_ip %}{% if op %}
<span class="operation-wrapper">
<a href="{{op.get_url}}?port_id={{ i.port_id }}_{{ i.ipv4 }}"
class="btn btn-{{op.effect}} btn-xs operation"
{% if op.disabled %}disabled{% endif %}>{% trans "Associate public IP" %}
</a>
</span>
{% endif %}{% endwith %}
{% endif %} {% endif %}
</div><!-- /ipv6 --> </span>
{% include "dashboard/vm-detail/_network-port-add.html" %}
</div> </div>
</div>
{% endif %} {% endif %}
{# {% if i.host %}#}
{# <div class="col-md-7">#}
{# <ul class="nav nav-pills pull-right">#}
{# <li class="active"><a href="#ipv4_{{ i.host.vlan.pk }}" data-toggle="pill" class="text-center">{% trans "IPv4" %}</a></li>#}
{# <li><a href="#ipv6_{{ i.host.vlan.pk }}" data-toggle="pill" class="text-center">{% trans "IPv6" %}</a></li>#}
{# </ul>#}
{# <h4>{% trans "Port access" %}</h4>#}
{# <div class="tab-content" style="padding-top: 10px;">#}
{# <div class="tab-pane active" id="ipv4_{{ i.host.vlan.pk }}">#}
{# <table class="table table-striped rule-table">#}
{# <thead>#}
{# <tr><th>#}
{# <i class="fa fa-globe fa-2x"></i>#}
{# <i class="fa fa-long-arrow-right fa-2x"></i>#}
{# </th><th>#}
{# <i class="fa fa-shield fa-2x"></i>#}
{# </th><th colspan="2">#}
{# <i class="fa fa-long-arrow-right fa-2x"></i>#}
{# <i class="fa fa-desktop fa-2x"></i>#}
{# </th></tr>#}
{# </thead>#}
{# <tbody>#}
{# {% for l in i.host.list_ports %}#}
{# {% if l.ipv4 %}#}
{# <tr>#}
{# <td>#}
{# {% display_portforward4 l %}#}
{# </td>#}
{# <td><i class="fa fa-long-arrow-right"></i></td>#}
{# <td>#}
{# {{ l.private }}/{{ l.proto }}#}
{# </td>#}
{# <td>#}
{# <span class="operation-wrapper">#}
{# <a href="{{ op.remove_port.get_url }}?rule={{ l.ipv4.pk }}"#}
{# class="btn btn-link btn-xs operation"#}
{# title="{% trans "Remove" %}"#}
{# {% if not op.remove_port %}disabled{% endif %}>#}
{# <i class="fa fa-times"><span class="sr-only">{% trans "Remove" %}</span></i>#}
{# </a>#}
{# </span>#}
{# </td>#}
{# </tr>#}
{# {% endif %}#}
{# {% endfor %}#}
{# </tbody>#}
{# </table>#}
{# </div> <!-- /ipv4 -->#}
{# <div class="tab-pane" id="ipv6_{{ i.host.vlan.pk }}">#}
{# {% if i.host.ipv6 %}#}
{# <table class="table table-striped rule-table">#}
{# <thead>#}
{# <tr><th>#}
{# <i class="fa fa-globe fa-2x"></i>#}
{# </th><th>#}
{# <i class="fa fa-long-arrow-right fa-2x"></i>#}
{# </th><th colspan="2">#}
{# <i class="fa fa-desktop fa-2x"></i>#}
{# </th></tr>#}
{# </thead>#}
{# <tbody>#}
{# {% for l in i.host.list_ports %}#}
{# {% if l.ipv6 %}#}
{# <tr>#}
{# <td>#}
{# {% display_portforward6 l %}#}
{# </td>#}
{# <td><i class="fa fa-long-arrow-right"></i></td>#}
{# <td>#}
{# {{ l.private }}/{{ l.proto }}#}
{# </td>#}
{# <td>#}
{# <a href="{{ op.remove_port.get_url }}?rule={{ l.ipv4.pk }}" class="btn btn-link btn-xs vm-details-remove-port" data-rule="{{ l.ipv6.pk }}" title="{% trans "Remove" %}" {% if not op.remove_port %}disabled{% endif %}>#}
{# <i class="fa fa-times"><span class="sr-only">{% trans "Remove" %}</span></i>#}
{# </a>#}
{# </td>#}
{# </tr>#}
{# {% endif %}#}
{# {% endfor %}#}
{# </tbody>#}
{# </table>#}
{# {% else %}#}
{# <h4>{% trans "This VM doesn't have an IPv6 address!" %}</h4>#}
{# {% endif %}#}
{# </div><!-- /ipv6 -->#}
{# {% include "dashboard/vm-detail/_network-port-add.html" %}#}
{# </div>#}
{# </div>#}
{# {% endif %}#}
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
...@@ -63,7 +63,7 @@ from .util import ( ...@@ -63,7 +63,7 @@ from .util import (
) )
from ..forms import ( from ..forms import (
AclUserOrGroupAddForm, VmResourcesForm, VmCustomizeForm, VmDeployForm, VmFromPlainImageForm, VmRemoveInterfaceForm, AclUserOrGroupAddForm, VmResourcesForm, VmCustomizeForm, VmDeployForm, VmFromPlainImageForm, VmRemoveInterfaceForm,
VmAddInterfaceForm, VmSaveForm) VmAddInterfaceForm, VmSaveForm, VmPortAddForm, VmPublicIpAddForm)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -122,7 +122,14 @@ class VmDetailView(LoginRequiredMixin, GraphMixin, DetailView): ...@@ -122,7 +122,14 @@ class VmDetailView(LoginRequiredMixin, GraphMixin, DetailView):
try: try:
vnc_console = openstack_api.nova.server_vnc_console(self.request, instance.id) vnc_console = openstack_api.nova.server_vnc_console(self.request, instance.id)
except: except:
pass #TODO pass
if vnc_console is None:
try:
vnc_console = openstack_api.nova.server_spice_console(self.request, instance.id)
except:
pass
context.update({ context.update({
'graphite_enabled': settings.GRAPHITE_URL is not None, 'graphite_enabled': settings.GRAPHITE_URL is not None,
'vnc_url': vnc_console.url if vnc_console else None, 'vnc_url': vnc_console.url if vnc_console else None,
...@@ -149,6 +156,7 @@ class VmDetailView(LoginRequiredMixin, GraphMixin, DetailView): ...@@ -149,6 +156,7 @@ class VmDetailView(LoginRequiredMixin, GraphMixin, DetailView):
ports = openstack_api.neutron.port_list(self.request) ports = openstack_api.neutron.port_list(self.request)
instance_ports = [p for p in ports if p.device_id == self.object.id] instance_ports = [p for p in ports if p.device_id == self.object.id]
instance_ports_by_id = {p.id: p for p in ports if p.device_id == self.object.id}
instance_net_ids = [p.network_id for p in instance_ports] instance_net_ids = [p.network_id for p in instance_ports]
all_networks = openstack_api.neutron.network_list(self.request) all_networks = openstack_api.neutron.network_list(self.request)
...@@ -166,11 +174,18 @@ class VmDetailView(LoginRequiredMixin, GraphMixin, DetailView): ...@@ -166,11 +174,18 @@ class VmDetailView(LoginRequiredMixin, GraphMixin, DetailView):
for port in instance_ports: for port in instance_ports:
instance_networks[port.network_id].ipv4 = port.fixed_ips[0]['ip_address'] instance_networks[port.network_id].ipv4 = port.fixed_ips[0]['ip_address']
instance_networks[port.network_id].port_id = port.id
# set default subnets for networks # set default subnets for networks
for id in instance_networks: for id in instance_networks:
instance_networks[id].subnet = instance_networks[id].subnets[0] instance_networks[id].subnet = instance_networks[id].subnets[0]
floating_ips = openstack_api.neutron.tenant_floating_ip_list(self.request)
for floating_ip in floating_ips:
if floating_ip.port_id in instance_ports_by_id.keys():
port = instance_ports_by_id[floating_ip.port_id]
instance_networks[port.network_id].public_ip = floating_ip.ip
context['networks'] = instance_networks.values() context['networks'] = instance_networks.values()
# context['vlans'] = Vlan.get_objects_with_level( # context['vlans'] = Vlan.get_objects_with_level(
...@@ -537,6 +552,25 @@ class VmAddInterfaceView(FormOperationMixin, VmOperationView): ...@@ -537,6 +552,25 @@ class VmAddInterfaceView(FormOperationMixin, VmOperationView):
# return val # return val
# #
# #
class VmPublicIpAddView(FormOperationMixin, VmOperationView):
op = 'add_public_ip'
show_in_toolbar = False
icon = 'plus'
effect = "success"
form_class = VmPublicIpAddForm
def get_form_kwargs(self):
ip_pools = openstack_api.neutron.floating_ip_pools_list(self.request)
port_id = self.request.GET.get('port_id')
val = super(VmPublicIpAddView, self).get_form_kwargs()
val.update({'pools': ip_pools})
val.update({'port_id': port_id})
return val
class VmSaveView(FormOperationMixin, VmOperationView): class VmSaveView(FormOperationMixin, VmOperationView):
op = 'save_as_template' op = 'save_as_template'
...@@ -802,6 +836,7 @@ vm_ops = OrderedDict([ ...@@ -802,6 +836,7 @@ vm_ops = OrderedDict([
('remove_interface', VmRemoveInterfaceView), ('remove_interface', VmRemoveInterfaceView),
# ('remove_port', VmPortRemoveView), # ('remove_port', VmPortRemoveView),
# ('add_port', VmPortAddView), # ('add_port', VmPortAddView),
('add_public_ip', VmPublicIpAddView),
# ('renew', VmRenewView), # ('renew', VmRenewView),
# ('resources_change', VmResourcesChangeView), # ('resources_change', VmResourcesChangeView),
# ('password_reset', VmOperationView.factory( # ('password_reset', VmOperationView.factory(
......
...@@ -438,7 +438,6 @@ class RemovePortOperation(InstanceOperation): ...@@ -438,7 +438,6 @@ class RemovePortOperation(InstanceOperation):
proto=rule.proto, port=rule.dport, host=rule.host) proto=rule.proto, port=rule.dport, host=rule.host)
rule.delete() rule.delete()
@register_operation @register_operation
class AddPortOperation(InstanceOperation): class AddPortOperation(InstanceOperation):
id = 'add_port' id = 'add_port'
...@@ -456,6 +455,14 @@ class AddPortOperation(InstanceOperation): ...@@ -456,6 +455,14 @@ class AddPortOperation(InstanceOperation):
ugettext_noop("open %(proto)s/%(port)d on %(host)s"), ugettext_noop("open %(proto)s/%(port)d on %(host)s"),
proto=proto, port=port, host=host) proto=proto, port=port, host=host)
@register_operation
class AddPublicIPOperation(InstanceOperation):
id = 'add_public_ip'
name = _("add public ip")
def _operation(self, request, pool, port_id):
floating_ip = openstack_api.neutron.tenant_floating_ip_allocate(request, pool, request.user.project_id)
openstack_api.neutron.floating_ip_associate(request, floating_ip.id, port_id)
@register_operation @register_operation
class RemoveDiskOperation(InstanceOperation): class RemoveDiskOperation(InstanceOperation):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment