Copy Designate-Dashboard to get started on Tatu dashboard.

This commit is contained in:
Pino de Candia 2018-01-08 16:34:38 +00:00
commit cdbe29c70b
160 changed files with 12375 additions and 0 deletions

33
.gitignore vendored Normal file
View File

@ -0,0 +1,33 @@
*.pyc
*.dat
TAGS
*.egg-info
*.egg
.eggs
build
.coverage
.coverage.*
.tox
cover
venv
.venv
*.sublime-workspace
*.sqlite
*.sqlite3
var/*
AUTHORS
ChangeLog
doc/source/api/*
doc/build/*
dist
*.orig
*.DS_Store
*.idea
.testrepository/*
functionaltests/tempest.log
functionaltests/.testrepository/
*.ipynb
/.ipynb_checkpoints/*
releasenotes/build
node_modules
npm-debug.log

4
.gitreview Normal file
View File

@ -0,0 +1,4 @@
[gerrit]
host=review.openstack.org
port=29418
project=openstack/designate-dashboard.git

4
.zuul.yaml Normal file
View File

@ -0,0 +1,4 @@
- project:
name: openstack/designate-dashboard
templates:
- designate-devstack-jobs

17
CONTRIBUTING.rst Normal file
View File

@ -0,0 +1,17 @@
If you would like to contribute to the development of OpenStack,
you must follow the steps in the "If you're a developer, start here"
section of this page:
http://wiki.openstack.org/HowToContribute
Once those steps have been completed, changes to OpenStack
should be submitted for review via the Gerrit tool, following
the workflow documented at:
http://wiki.openstack.org/GerritWorkflow
Pull requests submitted through GitHub will be ignored.
Bugs should be filed on Launchpad, not GitHub:
https://bugs.launchpad.net/designatedashboard

4
HACKING.rst Normal file
View File

@ -0,0 +1,4 @@
designatedashboard Style Commandments
===============================================
Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/

175
LICENSE Normal file
View File

@ -0,0 +1,175 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

79
README.rst Normal file
View File

@ -0,0 +1,79 @@
========================
Team and repository tags
========================
.. image:: http://governance.openstack.org/badges/designate-dashboard.svg
:target: http://governance.openstack.org/reference/tags/index.html
.. Change things from this point on
===============================
designatedashboard
===============================
Designate Horizon UI bits
* Free software: Apache license
Features
--------
* TODO
Howto
-----
1. Package the designatedashboard by running::
python setup.py sdist
This will create a python egg in the dist folder, which can be used to install
on the horizon machine or within horizon's python virtual environment.
-- or --
Install directly from source by running "python setup.py --install"
Note: On some systems python may throw an error like
'Exception: Versioning for this project requires either an sdist tarball, or access
to an upstream git repository'
this seems to be a result of mismatched pbr versioning. A hacking workaround for development
purposes is replacing the pbr call with a hard-coded version (e.g. '1.0.1') in
designatedashboard/__init__.py.
2. Copy panel plugin files into your Horizon config. These files can be found in designatedashboard/enabled
and should be copied to /usr/share/openstack-dashboard/openstack_dashboard/local/enabled or the
equivalent directory for your openstack-dashboard install.
3. Make sure your keystone catalog contains endpoints for service type 'dns'. If no such endpoints are
found, the designatedashboard panels will not render.
4. (Optional) Copy the designate policy file into horizon's policy files folder, and add this config::
'dns': 'designate_policy.json',
5. (Optional) Within your horizon settings file(s) (either the local settings or the other settings.py), add
the line below. This will make it so the record create/update screen uses a drop down of your floating ip
addresses instead of a free form text field::
DESIGNATE = { 'records_use_fips': True }
Test
----
* How to run JS tests:
* Install npm and nodejs=4.8.4
$ ``sudo apt-get install npm``
$ ``curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -``
$ ``sudo apt-get install -y nodejs``
1. ``npm install`` (to create virtual environment and install all dependencies in package.json)
2. ``npm run lint`` for eslint
3. ``npm run test`` for JS unit tests

5
babel-django.cfg Normal file
View File

@ -0,0 +1,5 @@
[extractors]
django = django_babel.extract:extract_django
[python: **.py]
[django: **/templates/**.html]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import pbr.version
__version__ = pbr.version.VersionInfo(
'designate-dashboard').version_string()

View File

@ -0,0 +1 @@
from designatedashboard.api import designate # noqa

View File

@ -0,0 +1,171 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from __future__ import absolute_import
from designateclient.v1 import Client # noqa
from designateclient.v1.domains import Domain # noqa
from designateclient.v1.records import Record # noqa
from django.conf import settings # noqa
from horizon import exceptions
from openstack_dashboard.api.base import url_for # noqa
from oslo_log import log as logging
LOG = logging.getLogger(__name__)
def designateclient(request):
designate_url = ""
try:
designate_url = url_for(request, 'dns')
except exceptions.ServiceCatalogException:
LOG.debug('no dns service configured.')
return None
insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
cacert = getattr(settings, 'OPENSTACK_SSL_CACERT', None)
return Client(endpoint=designate_url,
token=request.user.token.id,
username=request.user.username,
tenant_id=request.user.project_id,
insecure=insecure,
cacert=cacert)
def domain_get(request, domain_id):
d_client = designateclient(request)
if d_client is None:
return []
return d_client.domains.get(domain_id)
def domain_list(request):
d_client = designateclient(request)
if d_client is None:
return []
return d_client.domains.list()
def domain_create(request, name, email, ttl=None, description=None):
d_client = designateclient(request)
if d_client is None:
return None
options = {
'description': description,
}
# TTL needs to be optionally added as argument because the client
# won't accept a None value
if ttl is not None:
options['ttl'] = ttl
domain = Domain(name=name, email=email, **options)
return d_client.domains.create(domain)
def domain_update(request, domain_id, email, ttl, description=None):
d_client = designateclient(request)
if d_client is None:
return None
# A quirk of the designate client is that you need to start with a
# base record and then update individual fields in order to persist
# the data. The designate client will only send the 'changed' fields.
domain = Domain(id=domain_id, name='', email='')
domain.email = email
domain.ttl = ttl
domain.description = description
return d_client.domains.update(domain)
def domain_delete(request, domain_id):
d_client = designateclient(request)
if d_client is None:
return []
return d_client.domains.delete(domain_id)
def server_list(request, domain_id):
d_client = designateclient(request)
if d_client is None:
return []
return d_client.domains.list_domain_servers(domain_id)
def record_list(request, domain_id):
d_client = designateclient(request)
if d_client is None:
return []
return d_client.records.list(domain_id)
def record_get(request, domain_id, record_id):
d_client = designateclient(request)
if d_client is None:
return []
return d_client.records.get(domain_id, record_id)
def record_delete(request, domain_id, record_id):
d_client = designateclient(request)
if d_client is None:
return []
return d_client.records.delete(domain_id, record_id)
def record_create(request, domain_id, **kwargs):
d_client = designateclient(request)
if d_client is None:
return []
record = Record(**kwargs)
return d_client.records.create(domain_id, record)
def record_update(request, domain_id, record_id, **kwargs):
d_client = designateclient(request)
if d_client is None:
return []
# A quirk of the designate client is that you need to start with a
# base record and then update individual fields in order to persist
# the data. The designate client will only send the 'changed' fields.
record = Record(
id=record_id,
type='A',
name='',
data='')
record.type = kwargs.get('type', None)
record.name = kwargs.get('name', None)
record.data = kwargs.get('data', None)
record.priority = kwargs.get('priority', None)
record.ttl = kwargs.get('ttl', None)
record.description = kwargs.get('description', None)
return d_client.records.update(domain_id, record)
def quota_get(request, project_id=None):
if not project_id:
project_id = request.user.project_id
d_client = designateclient(request)
return d_client.quotas.get(project_id)

View File

@ -0,0 +1,16 @@
# (c) Copyright <year(s)> Hewlett Packard Enterprise Development LP
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""REST API for Horizon dashboard Javascript code.
"""
from . import passthrough # noqa

View File

@ -0,0 +1,119 @@
# Copyright 2016, Hewlett Packard Enterprise Development, LP
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""API for the passthrough service.
"""
from django.conf import settings
from django.views import generic
import functools
import requests
from requests.exceptions import HTTPError
from horizon import exceptions
from openstack_dashboard.api import base
from openstack_dashboard.api.rest import urls
from openstack_dashboard.api.rest import utils as rest_utils
from oslo_log import log as logging
LOG = logging.getLogger(__name__)
def _passthrough_request(request_method, url,
request, data=None, params=None):
"""Makes a request to the appropriate service API with an optional payload.
Should set any necessary auth headers and SSL parameters.
"""
# Set verify if a CACERT is set and SSL_NO_VERIFY isn't True
verify = getattr(settings, 'OPENSTACK_SSL_CACERT', None)
if getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False):
verify = False
service_url = _get_service_url(request, 'dns')
request_url = '{}{}'.format(
service_url,
url if service_url.endswith('/') else ('/' + url)
)
response = request_method(
request_url,
headers={'X-Auth-Token': request.user.token.id},
json=data,
verify=verify,
params=params
)
try:
response.raise_for_status()
except HTTPError as e:
LOG.debug(e.response.content)
for error in rest_utils.http_errors:
if (e.response.status_code == getattr(error, 'status_code', 0) and
exceptions.HorizonException in error.__bases__):
raise error
raise
return response
# Create some convenience partial functions
passthrough_get = functools.partial(_passthrough_request, requests.get)
passthrough_post = functools.partial(_passthrough_request, requests.post)
passthrough_put = functools.partial(_passthrough_request, requests.put)
passthrough_patch = functools.partial(_passthrough_request, requests.patch)
passthrough_delete = functools.partial(_passthrough_request, requests.delete)
def _get_service_url(request, service):
"""Get service's URL from keystone; allow an override in settings"""
service_url = getattr(settings, service.upper() + '_URL', None)
try:
service_url = base.url_for(request, service)
except exceptions.ServiceCatalogException:
pass
# Currently the keystone endpoint is http://host:port/
# without the version.
return service_url
@urls.register
class Passthrough(generic.View):
"""Pass-through API for executing service requests.
Horizon only adds auth and CORS proxying.
"""
url_regex = r'dns/(?P<path>.+)$'
@rest_utils.ajax()
def get(self, request, path):
return passthrough_get(path, request).json()
@rest_utils.ajax()
def post(self, request, path):
data = dict(request.DATA) if request.DATA else {}
return passthrough_post(path, request, data).json()
@rest_utils.ajax()
def put(self, request, path):
data = dict(request.DATA) if request.DATA else {}
return passthrough_put(path, request, data).json()
@rest_utils.ajax()
def patch(self, request, path):
data = dict(request.DATA) if request.DATA else {}
return passthrough_patch(path, request, data).json()
@rest_utils.ajax()
def delete(self, request, path):
return passthrough_delete(path, request).json()

View File

@ -0,0 +1,549 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import functools
import re
import six
from designateclient import exceptions as designate_exceptions
from django.core.exceptions import ValidationError # noqa
from django.core import validators
from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import forms
from horizon import messages
from designatedashboard import api
from designatedashboard.dashboards.project.dns_domains.utils\
import limit_records_to_fips
from oslo_log import log as logging
LOG = logging.getLogger(__name__)
MAX_TTL = 2147483647
# These regexes were given to me by Kiall Mac Innes here:
# https://gerrit.hpcloud.net/#/c/25300/2/
DOMAIN_NAME_REGEX = r'^(?!.{255,})(?:(?!\-)[A-Za-z0-9_\-]{1,63}(?<!\-)\.)+$'
WILDCARD_DOMAIN_NAME_REGEX = r'^(?!.{255,})(?:(^\*|(?!\-)[A-Za-z0-9_\-]{1,63})(?<!\-)\.)+$' # noqa
SRV_NAME_REGEX = r'^(?:_[A-Za-z0-9_\-]{1,62}\.){2}'
SRV_DATA_REGEX = r'^(?:(?:6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[1-5][0-9]{4}|[1-9][0-9]{1,3}|[0-9])\s){2}(?!.{255,})((?!\-)[A-Za-z0-9_\-]{1,63}(?<!\-)\.)+$' # noqa
SSHFP_DATA_REGEX = r'^[1-4]\s[1-2]\s\b([0-9a-fA-F]{5,40}|[0-9a-fA-F]{64})\b$'
# The max length for a dns label
NAME_MAX_LENGTH = 63
def handle_exc(func):
@functools.wraps(func)
def wrapped(form, request, *args, **kwargs):
try:
return func(form, request, *args, **kwargs)
except designate_exceptions.RemoteError as ex:
msg = ""
data = {}
if six.text_type(ex) is not None:
data['message'] = six.text_type(ex)
msg += "Error: %(message)s"
else:
data["type"] = ex.type
msg += "Error Type: %(type)s"
if ex.code >= 500:
msg += " (Request ID: %(request_id)s"
data["request_id"] = ex.request_id
form.api_error(_(msg) % data) # noqa
return False
except Exception:
messages.error(request, form.exc_message)
return True
return wrapped
class DomainForm(forms.SelfHandlingForm):
'''Base class for DomainCreate and DomainUpdate forms.
Sets-up all of the common form fields.
'''
name = forms.RegexField(
label=_("Domain Name"),
regex=DOMAIN_NAME_REGEX,
error_messages={'invalid': _('Enter a valid domain name.')},
)
email = forms.EmailField(
label=_("Email"),
max_length=255,
)
ttl = forms.IntegerField(
label=_("TTL (seconds)"),
min_value=1,
max_value=MAX_TTL,
required=False,
)
description = forms.CharField(
label=_("Description"),
required=False,
max_length=160,
widget=forms.Textarea(),
)
class DomainCreate(DomainForm):
'''Form for creating new domain records.
Name and email address are
required.
'''
exc_message = _("Unable to create domain.")
@handle_exc
def handle(self, request, data):
domain = api.designate.domain_create(
request,
name=data['name'],
email=data['email'],
ttl=data['ttl'],
description=data['description'])
messages.success(request,
_('Domain %(name)s created.') %
{"name": domain.name})
return domain
class DomainUpdate(DomainForm):
'''Form for displaying domain record details and updating them.'''
exc_message = _('Unable to update domain.')
id = forms.CharField(
required=False,
widget=forms.HiddenInput()
)
serial = forms.CharField(
label=_("Serial"),
required=False,
widget=forms.TextInput(attrs={'readonly': 'readonly'}),
)
created_at = forms.CharField(
label=_("Created At"),
required=False,
widget=forms.TextInput(attrs={'readonly': 'readonly'}),
)
updated_at = forms.CharField(
label=_("Updated At"),
required=False,
widget=forms.TextInput(attrs={'readonly': 'readonly'}),
)
def __init__(self, request, *args, **kwargs):
super(DomainUpdate, self).__init__(request, *args, **kwargs)
# Mark name as read-only
self.fields['name'].required = False
self.fields['name'].widget.attrs['readonly'] = 'readonly'
self.fields['ttl'].required = True
# Customize display order for fields
self.fields.keyOrder = [
'id',
'name',
'serial',
'email',
'ttl',
'description',
'created_at',
'updated_at',
]
@handle_exc
def handle(self, request, data):
domain = api.designate.domain_update(
request,
domain_id=data['id'],
email=data['email'],
ttl=data['ttl'],
description=data['description'])
messages.success(request,
_('Domain %(name)s updated.') %
{"name": domain.name})
return domain
class PrefixWidget(forms.TextInput):
def render(self, name, value, attrs=None):
template_name = 'project/dns_domains/prefix_html_widget.html'
result = super(PrefixWidget, self).render(name, value, attrs)
view_data = {'input': result,
'suffix': getattr(self, "suffix", '')}
return render_to_string(template_name, view_data)
class RecordForm(forms.SelfHandlingForm):
'''Base class for RecordCreate and RecordUpdate forms.
Sets-up all of
the form fields and implements the complex validation logic.
'''
domain_id = forms.CharField(
widget=forms.HiddenInput())
domain_name = forms.CharField(
widget=forms.HiddenInput())
type = forms.ChoiceField(
label=_("Record Type"),
required=False,
choices=[
('a', _('A - Address record')),
('aaaa', _('AAAA - IPv6 address record')),
('cname', _('CNAME - Canonical name record')),
('mx', _('MX - Mail exchange record')),
('ptr', _('PTR - Pointer record')),
('spf', _('SPF - Sender Policy Framework')),
('srv', _('SRV - Service locator')),
('sshfp', _('SSHFP - SSH Public Key Fingerprint')),
('txt', _('TXT - Text record')),
],
widget=forms.Select(attrs={
'class': 'switchable',
'data-slug': 'record_type',
}),
)
name = forms.CharField(
required=False,
widget=PrefixWidget(attrs={
'class': 'switched',
'data-switch-on': 'record_type',
'data-record_type-a': _('Name'),
'data-record_type-aaaa': _('Name'),
'data-record_type-cname': _('Name'),
'data-record_type-mx': _('Name'),
'data-record_type-ns': _('Name'),
'data-record_type-ptr': _('Name'),
'data-record_type-soa': _('Name'),
'data-record_type-spf': _('Name'),
'data-record_type-srv': _('Name'),
'data-record_type-sshfp': _('Name'),
'data-record_type-txt': _('Name'),
}),
)
data = forms.CharField(
required=False,
widget=forms.TextInput(attrs={
'class': 'switched',
'data-switch-on': 'record_type',
'data-record_type-a': _('IP Address'),
'data-record_type-aaaa': _('IP Address'),
'data-record_type-cname': _('Canonical Name'),
'data-record_type-ns': _('Name Server'),
'data-record_type-mx': _('Mail Server'),
'data-record_type-ptr': _('PTR Domain Name'),
'data-record_type-soa': _('Value'),
'data-record_type-srv': _('Value'),
}),
)
ip_addr = forms.ChoiceField(
required=False,
widget=forms.Select(attrs={
'class': 'switched',
'data-switch-on': 'record_type',
'data-record_type-a': _('IP Address'),
'data-record_type-aaaa': _('IP Address'),
}),
)
txt = forms.CharField(
label=_('TXT'),
required=False,
widget=forms.Textarea(attrs={
'class': 'switched',
'data-switch-on': 'record_type',
'data-record_type-txt': _('Text'),
'data-record_type-spf': _('Text'),
'data-record_type-sshfp': _('Text'),
}),
)
priority = forms.IntegerField(
min_value=0,
max_value=65535,
required=False,
widget=forms.TextInput(attrs={
'class': 'switched',
'data-switch-on': 'record_type',
'data-record_type-mx': _('Priority'),
'data-record_type-srv': _('Priority'),
}),
)
ttl = forms.IntegerField(
label=_('TTL'),
min_value=1,
max_value=MAX_TTL,
required=False,
widget=forms.TextInput(attrs={
'class': 'switched',
'data-switch-on': 'record_type',
'data-record_type-a': _('TTL'),
'data-record_type-aaaa': _('TTL'),
'data-record_type-cname': _('TTL'),
'data-record_type-mx': _('TTL'),
'data-record_type-ptr': _('TTL'),
'data-record_type-soa': _('TTL'),
'data-record_type-spf': _('TTL'),
'data-record_type-srv': _('TTL'),
'data-record_type-sshfp': _('TTL'),
'data-record_type-txt': _('TTL'),
}),
)
description = forms.CharField(
label=_("Description"),
required=False,
max_length=160,
widget=forms.Textarea(),
)
def __init__(self, request, *args, **kwargs):
super(RecordForm, self).__init__(request, *args, **kwargs)
initial = kwargs.get('initial', {})
domain_suffix = "." + initial['domain_name']
self.fields['name'].widget.suffix = domain_suffix
self.fields['name'].max_length = min(NAME_MAX_LENGTH,
255 - len(domain_suffix))
if limit_records_to_fips():
del self.fields['data'].widget.attrs['data-record_type-a']
del self.fields['data'].widget.attrs['data-record_type-aaaa']
self.fields['ip_addr'].choices = \
self.populate_ip_addr_choices(request,
initial)
else:
del self.fields['ip_addr']
def _generate_fip_list(self, fips, instances):
instance_dict = {instance.id: instance for instance in instances}
for fip in fips:
instance_name = _("Unknown instance name")
if getattr(fip, "instance_id", "None") in instance_dict:
instance_name = instance_dict[getattr(fip, "instance_id")].name
yield (fip.ip, "%s (%s)" % (fip.ip, instance_name))
def populate_ip_addr_choices(self, request, initial):
results = [(None, _('Select an IP')), ]
if (initial.get('ip_addr') and
initial['ip_addr'] not in [fip.ip for fip in initial['fips']]):
"""The record is currently using an ip not in the list
of fips - this can happen when instance goes away or in
multi region setups
"""
results.append((initial['ip_addr'], initial['ip_addr']))
results.extend(self._generate_fip_list(initial['fips'],
initial['instances']))
if len(results) == 1:
messages.warning(request, _("There are no floating IP addresses "
"currently in use to select from."))
return results
def clean_type(self):
'''Type value needs to be uppercased before it is sent to the API.'''
return self.cleaned_data['type'].upper()
def clean(self):
'''Handles the validation logic for the domain record form.
Validation gets pretty complicated due to the fact that the different
record types (A, AAAA, MX, etc) have different requirements for
each of the fields.
'''
cleaned_data = super(RecordForm, self).clean()
record_type = cleaned_data['type']
domain_name = cleaned_data['domain_name']
if limit_records_to_fips():
ip_addr = cleaned_data.pop('ip_addr')
if (record_type in ['AAAA', 'A'] and limit_records_to_fips()):
cleaned_data['data'] = ip_addr
# Name field
if self._is_field_blank(cleaned_data, 'name'):
if record_type in ['CNAME', 'SRV']:
self._add_required_field_error('name')
elif record_type in ['MX', 'A', 'AAAA', 'TXT', 'PTR']:
cleaned_data['name'] = domain_name
else:
if record_type == 'SRV':
if not re.match(SRV_NAME_REGEX, cleaned_data['name']):
self._add_field_error('name', _('Enter a valid SRV name'))
else:
cleaned_data['name'] += domain_name
else:
cleaned_data['name'] += "." + domain_name
if not re.match(WILDCARD_DOMAIN_NAME_REGEX,
cleaned_data['name']):
self._add_field_error('name',
_('Enter a valid hostname. The '
'hostname should contain letters '
'and numbers, and be no more than '
'63 characters.'))
# Data field
if self._is_field_blank(cleaned_data, 'data'):
if record_type in ['A', 'AAAA', 'CNAME', 'MX', 'SRV']:
self._add_required_field_error('data')
else:
if record_type == 'A':
try:
validators.validate_ipv4_address(cleaned_data['data'])
except ValidationError:
self._add_field_error('data',
_('Enter a valid IPv4 address'))
elif record_type == 'AAAA':
try:
validators.validate_ipv6_address(cleaned_data['data'])
except ValidationError:
self._add_field_error('data',
_('Enter a valid IPv6 address'))
elif record_type in ['CNAME', 'MX', 'PTR']:
if not re.match(DOMAIN_NAME_REGEX, cleaned_data['data']):
self._add_field_error('data', _('Enter a valid hostname'))
elif record_type == 'SRV':
if not re.match(SRV_DATA_REGEX, cleaned_data['data']):
self._add_field_error('data',
_('Enter a valid SRV record'))
# Txt field
if self._is_field_blank(cleaned_data, 'txt'):
if record_type == 'TXT':
self._add_required_field_error('txt')
else:
if record_type == 'TXT':
cleaned_data['data'] = cleaned_data['txt']
if record_type == 'SSHFP':
if not re.match(SSHFP_DATA_REGEX, cleaned_data['txt']):
self._add_field_error('txt',
_('Enter a valid SSHFP record'))
cleaned_data['data'] = cleaned_data['txt']
cleaned_data.pop('txt')
# Priority field
# Check against '' instead of using _is_field_blank because we need to
# allow a valud of 0.
if ('priority' not in cleaned_data or
cleaned_data['priority'] == '' or
cleaned_data['priority'] is None):
if record_type in ['MX', 'SRV']:
self._add_required_field_error('priority')
# Rename 'id' to 'record_id'
if 'id' in cleaned_data:
cleaned_data['record_id'] = cleaned_data.pop('id')
# Remove domain_name
cleaned_data.pop('domain_name')
return cleaned_data
def _add_required_field_error(self, field):
'''Set a required field error on the specified field.'''
self._add_field_error(field, _('This field is required'))
def _add_field_error(self, field, msg):
'''Set the specified msg as an error on the field.'''
self._errors[field] = self.error_class([msg])
def _is_field_blank(self, cleaned_data, field):
'''Returns a flag indicating whether the specified field is blank.'''
return field in cleaned_data and not cleaned_data[field]
class RecordCreate(RecordForm):
'''Form for creating a new domain record.'''
exc_message = _('Unable to create record.')
@handle_exc
def handle(self, request, data):
record = api.designate.record_create(request, **data)
messages.success(request,
_('Domain record %(name)s created.') %
{"name": record.name})
return record
class RecordUpdate(RecordForm):
'''Form for editing a domain record.'''
exc_message = _('Unable to create record.')
id = forms.CharField(widget=forms.HiddenInput())
def __init__(self, request, *args, **kwargs):
super(RecordUpdate, self).__init__(request, *args, **kwargs)
# Force the type field to be read-only
self.fields['type'].widget.attrs['readonly'] = 'readonly'
if self['type'].value() in ('soa', 'ns'):
self.fields['type'].choices.append(('ns', _('NS')))
self.fields['type'].choices.append(('soa', _('SOA')))
self.fields['name'].widget.attrs['readonly'] = 'readonly'
self.fields['data'].widget.attrs['readonly'] = 'readonly'
self.fields['description'].widget.attrs['readonly'] = 'readonly'
self.fields['ttl'].widget.attrs['readonly'] = 'readonly'
# Filter the choice list so that it only contains the type for
# the current record. Ideally, we would just disable the select
# field, but that has the unfortunate side-effect of breaking
# the 'selectable' javascript code.
self.fields['type'].choices = (
[choice for choice in self.fields['type'].choices
if choice[0] == self.initial['type']])
@handle_exc
def handle(self, request, data):
if data['type'] in ('SOA', 'NS'):
return True
record = api.designate.record_update(request, **data)
messages.success(request,
_('Domain record %(name)s updated.') %
{"name": record.name})
return record

View File

@ -0,0 +1,26 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.utils.translation import ugettext_lazy as _ # noqa
import horizon
from openstack_dashboard.dashboards.project import dashboard
class DNSDomains(horizon.Panel):
name = _("Domains")
slug = 'dns_domains'
permissions = ('openstack.services.dns',)
dashboard.Project.register(DNSDomains)

View File

@ -0,0 +1,224 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.core import urlresolvers
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import messages
from horizon import tables
from horizon.utils import memoized
from designatedashboard import api
from openstack_dashboard import policy
from oslo_log import log as logging
LOG = logging.getLogger(__name__)
EDITABLE_RECORD_TYPES = (
"A",
"AAAA",
"CNAME",
"MX",
"PTR",
"SPF",
"SRV",
"SSHFP",
"TXT",
)
class CreateDomain(tables.LinkAction):
'''Link action for navigating to the CreateDomain view.'''
name = "create_domain"
verbose_name = _("Create Domain")
url = "horizon:project:dns_domains:create_domain"
classes = ("ajax-modal", "btn-create")
policy_rules = (("dns", "create_domain"),)
@memoized.memoized_method
def allowed(self, request, datum):
if policy.check((("dns", "get_quota"),), request):
try:
if self.table:
quota = api.designate.quota_get(request)
return quota['domains'] > len(self.table.data)
except Exception:
msg = _("The quotas could not be retrieved.")
messages.warning(request, msg)
return True
class EditDomain(tables.LinkAction):
'''Link action for navigating to the UpdateDomain view.'''
name = "edit_domain"
verbose_name = _("Edit Domain")
url = "horizon:project:dns_domains:update_domain"
classes = ("ajax-modal", "btn-edit")
policy_rules = (("dns", "update_domain"),)
class ManageRecords(tables.LinkAction):
'''Link action for navigating to the ManageRecords view.'''
name = "manage_records"
verbose_name = _("Manage Records")
url = "horizon:project:dns_domains:records"
classes = ("btn-edit")
policy_rules = (("dns", "get_records"),)
class DeleteDomain(tables.BatchAction):
'''Batch action for deleting domains.'''
name = "delete"
action_present = _("Delete")
action_past = _("Deleted")
data_type_singular = _("Domain")
data_type_plural = _("Domains")
classes = ('btn-danger', 'btn-delete')
policy_rules = (("dns", "delete_domain"),)
def action(self, request, domain_id):
api.designate.domain_delete(request, domain_id)
class CreateRecord(tables.LinkAction):
'''Link action for navigating to the CreateRecord view.'''
name = "create_record"
verbose_name = _("Create Record")
classes = ("ajax-modal", "btn-create")
policy_rules = (("dns", "create_record"),)
def get_link_url(self, datum=None):
url = "horizon:project:dns_domains:create_record"
return urlresolvers.reverse(url, kwargs=self.table.kwargs)
class EditRecord(tables.LinkAction):
'''Link action for navigating to the UpdateRecord view.'''
name = "edit_record"
verbose_name = _("Edit Record")
classes = ("ajax-modal", "btn-edit")
policy_rules = (("dns", "update_record"),)
def get_link_url(self, datum=None):
url = "horizon:project:dns_domains:update_record"
kwargs = {
'domain_id': datum.domain_id,
'record_id': datum.id,
}
return urlresolvers.reverse(url, kwargs=kwargs)
def allowed(self, request, record=None):
return record.type in EDITABLE_RECORD_TYPES
class DeleteRecord(tables.DeleteAction):
'''Link action for navigating to the UpdateRecord view.'''
data_type_singular = _("Record")
policy_rules = (("dns", "delete_record"),)
def delete(self, request, record_id):
domain_id = self.table.kwargs['domain_id']
return api.designate.record_delete(request, domain_id, record_id)
def allowed(self, request, record=None):
return record.type in EDITABLE_RECORD_TYPES
class BatchDeleteRecord(tables.BatchAction):
'''Batch action for deleting domain records.'''
name = "delete"
action_present = _("Delete")
action_past = _("Deleted")
data_type_singular = _("Record")
classes = ('btn-danger', 'btn-delete')
policy_rules = (("dns", "delete_record"),)
def action(self, request, record_id):
domain_id = self.table.kwargs['domain_id']
api.designate.record_delete(request, domain_id, record_id)
class DomainsTable(tables.DataTable):
'''Data table for displaying domain summary information.'''
name = tables.Column("name",
verbose_name=_("Name"),
link=("horizon:project:dns_domains:domain_detail"))
email = tables.Column("email",
verbose_name=_("Email"))
ttl = tables.Column("ttl",
verbose_name=_("TTL"))
serial = tables.Column("serial",
verbose_name=_("Serial"))
class Meta(object):
name = "domains"
verbose_name = _("Domains")
table_actions = (CreateDomain, DeleteDomain,)
row_actions = (ManageRecords, EditDomain, DeleteDomain,)
def record__details_link(record):
'''Returns a link to the view for updating DNS records.'''
return urlresolvers.reverse(
"horizon:project:dns_domains:view_record",
args=(record.domain_id, record.id))
class RecordsTable(tables.DataTable):
'''Data table for displaying summary information for a domains records.'''
name = tables.Column("name",
verbose_name=_("Name"),
link=record__details_link,
)
type = tables.Column("type",
verbose_name=_("Type")
)
data = tables.Column("data",
verbose_name=_("Data")
)
priority = tables.Column("priority",
verbose_name=_("Priority"),
)
ttl = tables.Column("ttl",
verbose_name=_("TTL")
)
class Meta(object):
name = "records"
verbose_name = _("Records")
table_actions = (CreateRecord,)
row_actions = (EditRecord, DeleteRecord,)
multi_select = False

View File

@ -0,0 +1,38 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n horizon humanize %}
{% block form_id %}{% endblock %}
{% block form_action %}{% url 'horizon:project:dns_domains:create_domain' %}{% endblock %}
{% block modal_id %}create_domain_modal{% endblock %}
{% block modal-header %}{% trans "Create Domain" %}{% endblock %}
{% block modal-body %}
<div class="left">
<fieldset>
{% include "horizon/common/_form_fields.html" %}
</fieldset>
</div>
<div class="right quota-dynamic">
<h3>{% trans "Description" %}:</h3>
<p>{% blocktrans %}
The Name field should contain a full-qualified domain name (with
trailing period).
{% endblocktrans %}</p>
<p>{% blocktrans %}
The Email field should contain a valid email address to be associated
with the domain.
{% endblocktrans %}</p>
<p>{% blocktrans %}
The optional TTL field can be any value between 1 and 2147483647
seconds.
{% endblocktrans %}</p>
</div>
{% endblock %}
{% block modal-footer %}
<input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Domain" %}" />
<a href="{% url 'horizon:project:dns_domains:index' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
{% endblock %}

View File

@ -0,0 +1,37 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n horizon humanize %}
{% block form_id %}{% endblock %}
{% block form_action %}{% url 'horizon:project:dns_domains:create_record' domain.id %}{% endblock %}
{% block modal_id %}create_record_modal{% endblock %}
{% block modal-header %}{% trans "Create Record for" %} {{ domain.name }}{% endblock %}
{% block modal-body %}
<div id="scoped-content">
{% include 'project/dns_domains/prefix_field_style.html' %}
<fieldset>
{% include "horizon/common/_form_fields.html" %}
</fieldset>
</div>
{% blocktrans %}
<p>
<strong>TTL</strong>
The TTL is the time-to-live for the record, in seconds.
</p>
<p>
See <a href="http://en.wikipedia.org/wiki/List_of_DNS_record_types" target="_designate_record_defs">more info</a> on record types.
</p>
{% endblocktrans %}
<script type="text/javascript">
// Empty hidden form fields when the record type is switched
// https://bugs.launchpad.net/designate/+bug/1525199
$("select#id_type.form-control.switchable").eq(0).change(function() {
$(this).closest('fieldset')
.find("input[type=text], textarea").filter(":hidden")
.val("");
})
</script>
{% endblock %}

View File

@ -0,0 +1,32 @@
{% load i18n sizeformat %}
<h3>{% trans "Domain Overview" %}</h3>
<div class="info detail">
<dl class="dl-horizontal">
<dt>{% trans "ID" %}</dt>
<dd>{{ domain.id|default:_("None") }}</dd>
<dt>{% trans "Name" %}</dt>
<dd>{{ domain.name|default:_("None") }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ domain.description|default:_("None") }}</dd>
<dt>{% trans "Serial" %}</dt>
<dd>{{ domain.serial|yesno|capfirst }}</dd>
<dt>{% trans "Email" %}</dt>
<dd>{{ domain.email|default:_("Unknown") }}</dd>
<dt>{% trans "TTL" %}</dt>
<dd>{{ domain.ttl|default:_("Unknown") }}</dd>
<dt>{% trans "Created" %}</dt>
{% if domain.created_at %}
<dd>{{ domain.created_at|parse_isotime }}</dd>
{% else %}
<dd>{% trans "Unknown" %}</dd>
{% endif %}
<dt>{% trans "Updated" %}</dt>
{% if domain.updated_at %}
<dd>{{ domain.updated_at|parse_isotime }}</dd>
{% else %}
<dd>{% trans "Unknown" %}</dd>
{% endif %}
</dl>
</div>

View File

@ -0,0 +1,36 @@
{% load i18n sizeformat %}
<h3><a href="{% url 'horizon:project:dns_domains:records' domain_id %}">{% trans "All Records" %}</a></h3>
<h4>{{ record.name|default:_("None") }}</h4>
<div class="info detail">
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd>{{ record.name|default:_("None") }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ record.id|default:_("None") }}</dd>
<dt>{% trans "Type" %}</dt>
<dd>{{ record.type|default:_("Unknown") }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ record.description|default:_("None") }}</dd>
<dt>{% trans "Record Data" %}</dt>
<dd>{{ record.data|default:_("None") }}</dd>
<dt>{% trans "Priority" %}</dt>
<dd>{{ record.priority|yesno|capfirst }}</dd>
<dt>{% trans "TTL" %}</dt>
<dd>{{ record.ttl|default:_("None") }}</dd>
<dt>{% trans "Created" %}</dt>
{% if record.created_at %}
<dd>{{ record.created_at|parse_isotime }}</dd>
{% else %}
<dd>{% trans "Unknown" %}</dd>
{% endif %}
<dt>{% trans "Updated" %}</dt>
{% if record.updated_at %}
<dd>{{ record.updated_at|parse_isotime }}</dd>
{% else %}
<dd>{% trans "Unknown" %}</dd>
{% endif %}
</dl>
</div>

View File

@ -0,0 +1,36 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% load url from future %}
{% block form_id %}update_domain_form{% endblock %}
{% block form_action %}{% url 'horizon:project:dns_domains:update_domain' domain.id %}{% endblock %}
{% block modal-header %}{% trans "Update Domain" %}{% endblock %}
{% block modal-body %}
<div class="left">
<fieldset>
{% include "horizon/common/_form_fields.html" %}
</fieldset>
</div>
<div class="right">
<h3>{% trans "Description" %}:</h3>
<p>{% blocktrans %}
From here you can edit the email address and TTL associated with a domain.
{% endblocktrans %}</p>
<p>{% blocktrans %}
The Email field should contain a valid email address to be associated
with the domain.
{% endblocktrans %}</p>
<p>{% blocktrans %}
The optional TTL field can be any value between 1 and 2147483647
seconds.
{% endblocktrans %}</p>
</div>
{% endblock %}
{% block modal-footer %}
<input class="btn btn-primary pull-right" type="submit" value="{% trans "Update Domain" %}" />
<a href="{% url 'horizon:project:dns_domains:index' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
{% endblock %}

View File

@ -0,0 +1,9 @@
{% extends "project/dns_domains/_create_record.html" %}
{% load i18n %}
{% load url from future %}
{% block form_id %}update_record_form{% endblock %}
{% block form_action %}{% url 'horizon:project:dns_domains:update_record' record.domain_id record.id %}{% endblock %}
{% block modal-header %}{% trans "Update Domain Record" %}{% endblock %}

View File

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Create Domain" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Create Domain") %}
{% endblock page_header %}
{% block main %}
{% include 'project/dns_domains/_create_domain.html' %}
{% endblock %}

View File

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Create Domain Record" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Create Domain Record") %}
{% endblock page_header %}
{% block main %}
{% include 'project/dns_domains/_create_record.html' %}
{% endblock %}

View File

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans 'Domain Detail' %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Domain") %}
{% endblock page_header %}
{% block main %}
{% include 'project/dns_domains/_domain_detail.html' %}
{% endblock %}

View File

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Domains" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Domains") %}
{% endblock page_header %}
{% block main %}
{{ table.render }}
{% endblock %}

View File

@ -0,0 +1,4 @@
<style type = "text/css" scoped>
.form_field_suffix { float: right; padding-top:10px; }
.form_field_prefix { display: block; overflow: hidden; }
</style>

View File

@ -0,0 +1,2 @@
<label class="form_field_suffix">{{ suffix }}</label>
<span class="form_field_prefix">{{ input }}</span>

View File

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans 'Record Detail' %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title="Record Detail" %}
{% endblock page_header %}
{% block main %}
{% include 'project/dns_domains/_record_detail.html' %}
{% endblock %}

View File

@ -0,0 +1,32 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans 'Domain Records' %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Domain Records") %}
{% endblock page_header %}
{% block main %}
<div class="sub-content grid-content">
<div class="page_title table_header">
<div>
<h3>
<a href="{% url 'horizon:project:dns_domains:index' %}">{% trans "Domains" %}</a> : {{ domain.name }} &rarr;
{% trans "Records" %}
</h3>
</div>
<div class="table_actions">
<a href="{% url 'horizon:project:dns_domains:index' %}" class="close">&times;</a>
</div>
</div>
<div class="nameservers_wrapper">
<h3>{% trans "Nameservers" %}</h3>
<ul>
{% for server in servers %}
<li>{{ server.name }}</li>
{% endfor %}
</ul>
</div>
{{ table.render }}
{% endblock %}

View File

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans 'Update Domain' %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title="Domain" %}
{% endblock page_header %}
{% block main %}
{% include 'project/dns_domains/_update_domain.html' %}
{% endblock %}

View File

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans 'Update Domain Record' %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title="Domain Record" %}
{% endblock page_header %}
{% block main %}
{% include 'project/dns_domains/_update_record.html' %}
{% endblock %}

View File

@ -0,0 +1,52 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.conf.urls import url, patterns # noqa
from .views import CreateDomainView # noqa
from .views import CreateRecordView # noqa
from .views import DomainDetailView # noqa
from .views import IndexView # noqa
from .views import RecordsView # noqa
from .views import UpdateDomainView # noqa
from .views import UpdateRecordView # noqa
from .views import ViewRecordDetailsView # noqa
urlpatterns = patterns(
'',
url(r'^$',
IndexView.as_view(),
name='index'),
url(r'^create/$',
CreateDomainView.as_view(),
name='create_domain'),
url(r'^(?P<domain_id>[^/]+)/update$',
UpdateDomainView.as_view(),
name='update_domain'),
url(r'^(?P<domain_id>[^/]+)$',
DomainDetailView.as_view(),
name='domain_detail'),
url(r'^(?P<domain_id>[^/]+)/records$',
RecordsView.as_view(),
name='records'),
url(r'^(?P<domain_id>[^/]+)/records/create$',
CreateRecordView.as_view(),
name='create_record'),
url(r'^(?P<domain_id>[^/]+)/records/(?P<record_id>[^/]+)/update$',
UpdateRecordView.as_view(),
name='update_record'),
url(r'^(?P<domain_id>[^/]+)/records/(?P<record_id>[^/]+)/$',
ViewRecordDetailsView.as_view(),
name='view_record'),
)

View File

@ -0,0 +1,20 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.conf import settings
def limit_records_to_fips():
# This method checks the settings to determine if the
# record creation / update screen should limit the ip input
# to be a dropdown of floating ips
return getattr(settings, "DESIGNATE",
{}).get("records_use_fips", False)

View File

@ -0,0 +1,243 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.core.urlresolvers import reverse, reverse_lazy # noqa
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import forms
from horizon import tables
from horizon.views import HorizonTemplateView # noqa
from openstack_dashboard.api.network import tenant_floating_ip_list
from openstack_dashboard.api.nova import server_list
from designatedashboard import api
from designatedashboard.api import rest # noqa
from .forms import DomainCreate # noqa
from .forms import DomainUpdate # noqa
from .forms import RecordCreate # noqa
from .forms import RecordUpdate # noqa
from .tables import DomainsTable # noqa
from .tables import RecordsTable # noqa
from .utils import limit_records_to_fips # noqa
class IndexView(tables.DataTableView):
table_class = DomainsTable
template_name = 'project/dns_domains/index.html'
def get_data(self):
try:
return api.designate.domain_list(self.request)
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve domain list.'))
return []
class CreateDomainView(forms.ModalFormView):
form_class = DomainCreate
template_name = 'project/dns_domains/create_domain.html'
success_url = reverse_lazy('horizon:project:dns_domains:index')
def get_object_display(self, obj):
return obj.ip
class DomainDetailView(HorizonTemplateView):
template_name = 'project/dns_domains/domain_detail.html'
def get_context_data(self, **kwargs):
context = super(DomainDetailView, self).get_context_data(**kwargs)
domain_id = self.kwargs['domain_id']
try:
context["domain"] = api.designate.domain_get(self.request,
domain_id)
table = DomainsTable(self.request)
context["actions"] = table.render_row_actions(context["domain"])
except Exception:
redirect = reverse('horizon:project:dns_domains:index')
exceptions.handle(self.request,
_('Unable to retrieve domain record.'),
redirect=redirect)
return context
class UpdateDomainView(forms.ModalFormView):
form_class = DomainUpdate
template_name = 'project/dns_domains/update_domain.html'
success_url = reverse_lazy('horizon:project:dns_domains:index')
def get_object(self):
domain_id = self.kwargs['domain_id']
try:
return api.designate.domain_get(self.request, domain_id)
except Exception:
redirect = reverse('horizon:project:dns_domains:index')
exceptions.handle(self.request,
_('Unable to retrieve domain record.'),
redirect=redirect)
def get_initial(self):
self.domain = self.get_object()
return self.domain
def get_context_data(self, **kwargs):
context = super(UpdateDomainView, self).get_context_data(**kwargs)
context["domain"] = self.domain
return context
class RecordsView(tables.DataTableView):
table_class = RecordsTable
template_name = 'project/dns_domains/records.html'
def get_data(self):
domain_id = self.kwargs['domain_id']
records = []
try:
self.domain = api.designate.domain_get(self.request, domain_id)
self.servers = api.designate.server_list(self.request, domain_id)
records = api.designate.record_list(self.request, domain_id)
except Exception:
redirect = reverse('horizon:project:dns_domains:index')
exceptions.handle(self.request,
_('Unable to retrieve record list.'),
redirect=redirect)
return records
def get_context_data(self, **kwargs):
context = super(RecordsView, self).get_context_data(**kwargs)
context['domain'] = self.domain
context['servers'] = self.servers
return context
class BaseRecordFormView(forms.ModalFormView):
cancel_label = _("Cancel")
def get_success_url(self):
return reverse('horizon:project:dns_domains:records',
args=(self.kwargs['domain_id'],))
def get_domain(self):
domain_id = self.kwargs['domain_id']
try:
return api.designate.domain_get(self.request, domain_id)
except Exception:
redirect = reverse('horizon:project:dns_domains:records',
args=(self.kwargs['domain_id'],))
exceptions.handle(self.request,
('Unable to retrieve domain record.'),
redirect=redirect)
# NotAuthorized errors won't be redirected automatically. Need
# to force the issue
raise exceptions.Http302(redirect)
def get_initial(self):
self.domain = self.get_domain()
results = {'domain_id': self.domain.id,
'domain_name': self.domain.name, }
if limit_records_to_fips():
results.update({'fips': tenant_floating_ip_list(self.request),
'instances': server_list(self.request)[0]})
return results
def get_context_data(self, **kwargs):
"""Set the cancel url
the cancel_url needs a variable in it
so we cannot do this with a simple class attr
this is critical to perform before the super.get_context_data
"""
self.cancel_url = reverse('horizon:project:dns_domains:records',
args=(self.kwargs['domain_id'],))
context = super(BaseRecordFormView, self).get_context_data(**kwargs)
context['domain'] = self.domain
return context
class CreateRecordView(BaseRecordFormView):
form_class = RecordCreate
submit_label = _("Create Record")
template_name = 'project/dns_domains/create_record.html'
class ViewRecordDetailsView(HorizonTemplateView):
template_name = 'project/dns_domains/record_detail.html'
def get_record(self):
domain_id = self.kwargs['domain_id']
record_id = self.kwargs['record_id']
try:
return api.designate.record_get(self.request, domain_id, record_id)
except Exception:
redirect = reverse('horizon:project:dns_domains:records',
args=(self.kwargs['domain_id'],))
exceptions.handle(self.request,
_('Unable to retrieve domain record.'),
redirect=redirect)
def get_context_data(self, **kwargs):
context = super(ViewRecordDetailsView, self).get_context_data(**kwargs)
self.record = self.get_record()
context["record"] = self.record
context["domain_id"] = self.kwargs['domain_id']
return context
class UpdateRecordView(BaseRecordFormView):
form_class = RecordUpdate
submit_label = _("Update Record")
template_name = 'project/dns_domains/update_record.html'
def get_record(self):
domain_id = self.kwargs['domain_id']
record_id = self.kwargs['record_id']
try:
return api.designate.record_get(self.request, domain_id, record_id)
except Exception:
redirect = reverse('horizon:project:dns_domains:records',
args=(self.kwargs['domain_id'],))
exceptions.handle(self.request,
_('Unable to retrieve domain record.'),
redirect=redirect)
def get_initial(self):
initial = super(UpdateRecordView, self).get_initial()
self.record = self.get_record()
initial.update({
'id': self.record.id,
'name': self.record.name.replace("." + initial['domain_name'], ''),
'data': self.record.data,
'txt': self.record.data,
'priority': self.record.priority,
'ttl': self.record.ttl,
'type': self.record.type.lower(),
'description': self.record.description,
})
if limit_records_to_fips():
initial.update({'ip_addr': self.record.data})
return initial
def get_context_data(self, **kwargs):
context = super(UpdateRecordView, self).get_context_data(**kwargs)
context["record"] = self.record
return context

View File

@ -0,0 +1 @@
from designatedashboard.api import rest # noqa

View File

@ -0,0 +1,25 @@
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.utils.translation import ugettext_lazy as _
import horizon
from openstack_dashboard.dashboards.project import dashboard
class ReverseDns(horizon.Panel):
name = _("Reverse DNS")
slug = 'reverse_dns'
permissions = ('openstack.services.dns',)
dashboard.Project.register(ReverseDns)

View File

@ -0,0 +1,22 @@
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.conf.urls import url
from designatedashboard.dashboards.project.ngdns.reverse_dns import views
urlpatterns = [
url('', views.IndexView.as_view(), name='index'),
]

View File

@ -0,0 +1,19 @@
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.views import generic
class IndexView(generic.TemplateView):
template_name = 'angular.html'

View File

@ -0,0 +1,25 @@
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.utils.translation import ugettext_lazy as _
import horizon
from openstack_dashboard.dashboards.project import dashboard
class Zones(horizon.Panel):
name = _("Zones")
slug = 'dnszones'
permissions = ('openstack.services.dns',)
dashboard.Project.register(Zones)

View File

@ -0,0 +1,22 @@
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.conf.urls import url
from designatedashboard.dashboards.project.ngdns.zones import views
urlpatterns = [
url('', views.IndexView.as_view(), name='index'),
]

View File

@ -0,0 +1,19 @@
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.views import generic
class IndexView(generic.TemplateView):
template_name = 'angular.html'

View File

@ -0,0 +1,20 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# The name of the panel group to be added to HORIZON_CONFIG. Required.
PANEL_GROUP = 'dns'
# The display name of the PANEL_GROUP. Required.
PANEL_GROUP_NAME = 'DNS'
# The name of the dashboard the PANEL_GROUP associated with. Required.
PANEL_GROUP_DASHBOARD = 'project'

View File

@ -0,0 +1,36 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from designatedashboard import exceptions
# The name of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'domains'
# The name of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'project'
# The name of the panel group the PANEL is associated with.
PANEL_GROUP = 'dns'
ADD_INSTALLED_APPS = ['designatedashboard']
ADD_EXCEPTIONS = {
'recoverable': exceptions.RECOVERABLE,
'not_found': exceptions.NOT_FOUND,
'unauthorized': exceptions.UNAUTHORIZED,
}
# Python panel class of the PANEL to be added.
ADD_PANEL = (
'designatedashboard.dashboards.project.dns_domains.panel.DNSDomains')
DISABLED = True

View File

@ -0,0 +1,40 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from designatedashboard import exceptions
# The name of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'dnszones'
# The name of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'project'
# The name of the panel group the PANEL is associated with.
PANEL_GROUP = 'dns'
ADD_EXCEPTIONS = {
'recoverable': exceptions.RECOVERABLE,
'not_found': exceptions.NOT_FOUND,
'unauthorized': exceptions.UNAUTHORIZED,
}
ADD_INSTALLED_APPS = ['designatedashboard']
# Python panel class of the PANEL to be added.
ADD_PANEL = (
'designatedashboard.dashboards.project.ngdns.zones.panel.Zones')
ADD_ANGULAR_MODULES = ['designatedashboard']
ADD_SCSS_FILES = ['designatedashboard/designatedashboard.scss']
AUTO_DISCOVER_STATIC_FILES = True

View File

@ -0,0 +1,38 @@
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from designatedashboard import exceptions
# The name of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'reverse_dns'
# The name of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'project'
# The name of the panel group the PANEL is associated with.
PANEL_GROUP = 'dns'
ADD_EXCEPTIONS = {
'recoverable': exceptions.RECOVERABLE,
'not_found': exceptions.NOT_FOUND,
'unauthorized': exceptions.UNAUTHORIZED,
}
# Python panel class of the PANEL to be added.
ADD_PANEL = (
'designatedashboard.dashboards.project.ngdns.reverse_dns.panel.ReverseDns')
ADD_ANGULAR_MODULES = ['designatedashboard']
ADD_SCSS_FILES = ['designatedashboard/designatedashboard.scss']
AUTO_DISCOVER_STATIC_FILES = True

View File

View File

@ -0,0 +1,29 @@
# Copyright (c) 2014 Rackspace Hosting.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from designateclient import exceptions as designateclient
from openstack_dashboard import exceptions
NOT_FOUND = exceptions.NOT_FOUND + (
designateclient.ResourceNotFound,
designateclient.NotFound,
)
RECOVERABLE = exceptions.RECOVERABLE + (
designateclient.BadRequest,
designateclient.Conflict,
)
UNAUTHORIZED = exceptions.UNAUTHORIZED + (
designateclient.Forbidden,
)

Binary file not shown.

View File

@ -0,0 +1,348 @@
# Stanislav Ulrych <stanislav.ulrych@ultimum.io>, 2016. #zanata
# Zbyněk Schwarz <zbynek.schwarz@gmail.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: designate-dashboard 6.0.0.0b2.dev3\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-11-21 15:00+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-11-17 07:24+0000\n"
"Last-Translator: Zbyněk Schwarz <zbynek.schwarz@gmail.com>\n"
"Language-Team: Czech\n"
"Language: cs\n"
"X-Generator: Zanata 3.9.6\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n"
msgid ""
"\n"
" From here you can edit the email address and TTL associated with a "
"domain.\n"
" "
msgstr ""
"\n"
" Zde můžete upravit emailovou adresu a TTL patřící k doméně.\n"
" "
msgid ""
"\n"
" The Email field should contain a valid email address to be associated\n"
" with the domain.\n"
" "
msgstr ""
"\n"
" Pole Email by mělo obsahovat platnou emailovou adresu, která je spojená\n"
" s doménou.\n"
" "
msgid ""
"\n"
" The Name field should contain a full-qualified domain name (with\n"
" trailing period).\n"
" "
msgstr ""
"\n"
" Pole Název by mělo obsahovat plně kvalifikovaný název domény (s \n"
" tečkou na \n"
" konci)."
msgid ""
"\n"
" The optional TTL field can be any value between 1 and 2147483647\n"
" seconds.\n"
" "
msgstr ""
"\n"
" TTL (volitelné) může být hodnota mezi 1 a 2147483647\n"
" sekund.\n"
" "
msgid ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" The TTL is the time-to-live for the record, in seconds.\n"
" </p>\n"
" <p>\n"
" See <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">more info</a> on record types.\n"
" </p>\n"
" "
msgstr ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" TTL je time-to-live záznamu, v sekundách.\n"
" </p>\n"
" <p>\n"
" Viz <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">více informací</a> o typech záznamů.\n"
" </p>\n"
" "
msgid "A - Address record"
msgstr "A - adresní záznam"
msgid "AAAA - IPv6 address record"
msgstr "AAAA - adresní záznam IPv6"
msgid "All Records"
msgstr "Všechny záznamy"
msgid "CNAME - Canonical name record"
msgstr "CNAME - záznam kanonického jména"
msgid "Cancel"
msgstr "Zrušit"
msgid "Canonical Name"
msgstr "Kanonické jméno"
msgid "Create Domain"
msgstr "Vytvořit doménu"
msgid "Create Domain Record"
msgstr "Vytvořit doménový záznam"
msgid "Create Record"
msgstr "Vytvořit záznam"
msgid "Create Record for"
msgstr "Vytvořit záznam pro"
msgid "Created"
msgstr "Vytvořeno"
msgid "Created At"
msgstr "Vytvořeno"
msgid "Data"
msgstr "Data"
msgid "Delete"
msgstr "Smazat"
msgid "Deleted"
msgstr "Smazáno"
msgid "Description"
msgstr "Popis"
msgid "Domain"
msgstr "Doména"
#, python-format
msgid "Domain %(name)s created."
msgstr "Doména %(name)s vytvořena."
#, python-format
msgid "Domain %(name)s updated."
msgstr "Doména %(name)s aktualizována."
msgid "Domain Detail"
msgstr "Detail domény"
msgid "Domain Name"
msgstr "Název domény"
msgid "Domain Overview"
msgstr "Přehled domén"
msgid "Domain Records"
msgstr "Doménové záznamy"
#, python-format
msgid "Domain record %(name)s created."
msgstr "Doménový záznam %(name)s vytvořen."
#, python-format
msgid "Domain record %(name)s updated."
msgstr "Doménový záznam %(name)s aktualizován."
msgid "Domains"
msgstr "Domény"
msgid "Edit Domain"
msgstr "Upravit doménu"
msgid "Edit Record"
msgstr "Upravit záznam"
msgid "Email"
msgstr "E-mail"
msgid "Enter a valid IPv4 address"
msgstr "Zadejte platnou IPv4 adresu"
msgid "Enter a valid IPv6 address"
msgstr "Zadejte platnou IPv6 adresu"
msgid "Enter a valid SRV name"
msgstr "Zadejte platné SRV jméno"
msgid "Enter a valid SRV record"
msgstr "Zadejte platný SRV záznam"
msgid "Enter a valid SSHFP record"
msgstr "Zadejte platný SSHFP záznam"
msgid "Enter a valid domain name."
msgstr "Zadejte platný název domény."
msgid "Enter a valid hostname"
msgstr "Zadejte platné jméno hostitele"
msgid ""
"Enter a valid hostname. The hostname should contain letters and numbers, and "
"be no more than 63 characters."
msgstr ""
"Zadejte platný název hostitele. Název hostitele by měl obsahovat písmena a "
"číslice a musí být maximálně 63 znaků."
msgid "ID"
msgstr "ID"
msgid "IP Address"
msgstr "IP adresa"
msgid "MX - Mail exchange record"
msgstr "MX - mailový záznam"
msgid "Mail Server"
msgstr "Mailový server"
msgid "Manage Records"
msgstr "Spravovat záznamy"
msgid "NS"
msgstr "NS"
msgid "Name"
msgstr "Název"
msgid "Name Server"
msgstr "Název serveru"
msgid "Nameservers"
msgstr "Jmenné servery"
msgid "None"
msgstr "Žádný"
msgid "PTR - Pointer record"
msgstr "PTR - záznam ukazatele"
msgid "PTR Domain Name"
msgstr "PTR doménové jméno"
msgid "Priority"
msgstr "Priorita"
msgid "Record"
msgstr "Záznam"
msgid "Record Data"
msgstr "Zaznamenat data"
msgid "Record Detail"
msgstr "Zaznamenat detail"
msgid "Record Type"
msgstr "Typ záznamu"
msgid "Records"
msgstr "Záznamy"
msgid "Reverse DNS"
msgstr "Reverzní DNS"
msgid "SOA"
msgstr "SOA"
msgid "SPF - Sender Policy Framework"
msgstr "SPF - Sender Policy Framework"
msgid "SRV - Service locator"
msgstr "SRV - lokátor služby"
msgid "SSHFP - SSH Public Key Fingerprint"
msgstr "SSHFP - Otisk veřejného klíče SSH"
msgid "Select an IP"
msgstr "Vyberte IP adresu"
msgid "Serial"
msgstr "Sériový"
msgid "TTL"
msgstr "TTL"
msgid "TTL (seconds)"
msgstr "TTL (ve vteřinách)"
msgid "TXT"
msgstr "TXT"
msgid "TXT - Text record"
msgstr "TXT - textový záznam"
msgid "Text"
msgstr "Text"
msgid "The quotas could not be retrieved."
msgstr "Nelze získat kvóty."
msgid "There are no floating IP addresses currently in use to select from."
msgstr "Žádné plovoucí IP nejsou k dispozici pro výběr."
msgid "This field is required"
msgstr "Toto pole je povinné"
msgid "Type"
msgstr "Typ"
msgid "Unable to create domain."
msgstr "Nelze vytvořit doménu."
msgid "Unable to create record."
msgstr "Nelze vytvořit záznam."
msgid "Unable to retrieve domain list."
msgstr "Nelze získat seznam domén."
msgid "Unable to retrieve domain record."
msgstr "Nelze získat doménový záznam."
msgid "Unable to retrieve record list."
msgstr "Nelze získat záznamy."
msgid "Unable to update domain."
msgstr "Nelze aktualizovat doménu."
msgid "Unknown"
msgstr "Neznámé"
msgid "Unknown instance name"
msgstr "Neznámé jméno instance"
msgid "Update Domain"
msgstr "Aktualizovat doménu"
msgid "Update Domain Record"
msgstr "Aktualizovat záznam domény"
msgid "Update Record"
msgstr "Aktualizovat záznam"
msgid "Updated"
msgstr "Aktualizováno"
msgid "Updated At"
msgstr "Aktualizováno"
msgid "Value"
msgstr "Hodnota"
msgid "Zones"
msgstr "Zóny"

Binary file not shown.

View File

@ -0,0 +1,351 @@
# Frank Kloeker <eumel@arcor.de>, 2016. #zanata
# Robert Simai <robert.simai@suse.com>, 2016. #zanata
msgid ""
msgstr ""
"Project-Id-Version: designate-dashboard 3.0.0.0rc2.dev5\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2016-09-29 13:19+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2016-10-13 04:32+0000\n"
"Last-Translator: Andreas Jaeger <jaegerandi@gmail.com>\n"
"Language-Team: German\n"
"Language: de\n"
"X-Generator: Zanata 3.7.3\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
msgid ""
"\n"
" From here you can edit the email address and TTL associated with a "
"domain.\n"
" "
msgstr ""
"\n"
" Hier können Sie die E-Mail-Adresse und TTL mit dazugehöriger Domäne "
"editieren.\n"
" "
msgid ""
"\n"
" The Email field should contain a valid email address to be associated\n"
" with the domain.\n"
" "
msgstr ""
"\n"
" Das E-Mail-Feld sollte eine gültige E-Mail-Adresse enthalten,\n"
" die der Domäne zugewiesen wird.\n"
" "
msgid ""
"\n"
" The Name field should contain a full-qualified domain name (with\n"
" trailing period).\n"
" "
msgstr ""
"\n"
" Das Namensfeld sollte einen vollqualifizierten Domänennamen enthalten "
"(mit\n"
" abschließendem Punkt).\n"
" "
msgid ""
"\n"
" The optional TTL field can be any value between 1 and 2147483647\n"
" seconds.\n"
" "
msgstr ""
"\n"
" Das optionale TTL Feld kann einen Wert zwischen 1 und 2147483647\n"
" Sekunden haben.\n"
" "
msgid ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" The TTL is the time-to-live for the record, in seconds.\n"
" </p>\n"
" <p>\n"
" See <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">more info</a> on record types.\n"
" </p>\n"
" "
msgstr ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" Die TTL ist die time-to-live für den Datensatz, in Sekunden.\n"
" </p>\n"
" <p>\n"
" Hier finden Sie <a href=\"http://en.wikipedia.org/wiki/"
"List_of_DNS_record_types\" target=\"_designate_record_defs\">mehr "
"Informationen</a> zu Datensatztypen.\n"
" </p>\n"
" "
msgid "A - Address record"
msgstr "A - Adress Datensatz"
msgid "AAAA - IPv6 address record"
msgstr "AAAA - IPv6 Adress Datensatz"
msgid "All Records"
msgstr "Alle Datensätze"
msgid "CNAME - Canonical name record"
msgstr "CNAME - Canonical Name Datensatz"
msgid "Cancel"
msgstr "Abbrechen"
msgid "Canonical Name"
msgstr "Canonical Name"
msgid "Create Domain"
msgstr "Domäne erstellen"
msgid "Create Domain Record"
msgstr "Erzeuge Datensatz für Domäne"
msgid "Create Record"
msgstr "Datensatz erzeugen"
msgid "Create Record for"
msgstr "Erzeuge Datensatz für"
msgid "Created"
msgstr "Erstellt"
msgid "Created At"
msgstr "Erstellt am"
msgid "Data"
msgstr "Daten"
msgid "Delete"
msgstr "Löschen"
msgid "Deleted"
msgstr "Gelöscht"
msgid "Description"
msgstr "Beschreibung"
msgid "Domain"
msgstr "Domäne"
#, python-format
msgid "Domain %(name)s created."
msgstr "Domäne %(name)s erstellt."
#, python-format
msgid "Domain %(name)s updated."
msgstr "Domäne %(name)s wurde geändert."
msgid "Domain Detail"
msgstr "Domänen Details"
msgid "Domain Name"
msgstr "Domänenname"
msgid "Domain Overview"
msgstr "Domänenübersicht"
msgid "Domain Records"
msgstr "Domänendatensatz"
#, python-format
msgid "Domain record %(name)s created."
msgstr "Domändatensatz %(name)s erstellt."
#, python-format
msgid "Domain record %(name)s updated."
msgstr "Domänendatensatz %(name)s aktualisiert."
msgid "Domains"
msgstr "Domänen"
msgid "Edit Domain"
msgstr "Domäne bearbeiten"
msgid "Edit Record"
msgstr "Datensatze bearbeiten"
msgid "Email"
msgstr "E-Mail"
msgid "Enter a valid IPv4 address"
msgstr "Geben Sie eine gültige IPv4 Addresse ein"
msgid "Enter a valid IPv6 address"
msgstr "Geben Sie eine gültige IPv6 Addresse ein"
msgid "Enter a valid SRV name"
msgstr "Geben Sie einen gültigen SRV Namen ein"
msgid "Enter a valid SRV record"
msgstr "Geben Sie einen gültigen SRV Datensatz ein"
msgid "Enter a valid SSHFP record"
msgstr "Geben Sie einen gültigen SSHFP Datensatz ein"
msgid "Enter a valid domain name."
msgstr "Geben Sie einen gültigen Domänennamen ein."
msgid "Enter a valid hostname"
msgstr "Geben Sie einen gültigen Hostnamen ein"
msgid ""
"Enter a valid hostname. The hostname should contain letters and numbers, and "
"be no more than 63 characters."
msgstr ""
"Geben Sie einen gültien Hostnamen ein. Der Hostname darf nur Buchstaben und "
"Nummern enthalten und darf nicht mehr als 63 Zeichen lang sein."
msgid "ID"
msgstr "ID"
msgid "IP Address"
msgstr "IP-Adresse"
msgid "MX - Mail exchange record"
msgstr "MX - Mail Austausch Datensatz"
msgid "Mail Server"
msgstr "Mailserver"
msgid "Manage Records"
msgstr "Datensätze verwalten"
msgid "NS"
msgstr "NS"
msgid "Name"
msgstr "Name"
msgid "Name Server"
msgstr "Nameserver"
msgid "Nameservers"
msgstr "Namensserver"
msgid "None"
msgstr "Keine"
msgid "PTR - Pointer record"
msgstr "PTR - Pointer Datensatz"
msgid "PTR Domain Name"
msgstr "PTR Domänenname"
msgid "Priority"
msgstr "Priorität"
msgid "Record"
msgstr "Datensatz"
msgid "Record Data"
msgstr "Datensatz"
msgid "Record Detail"
msgstr "Datensatzdetails"
msgid "Record Type"
msgstr "Datensatztyp"
msgid "Records"
msgstr "Datensätze"
msgid "Reverse DNS"
msgstr "Reverse DNS"
msgid "SOA"
msgstr "SOA"
msgid "SPF - Sender Policy Framework"
msgstr "SPF - Sender Policy Framework"
msgid "SRV - Service locator"
msgstr "SRV - Dienstezeiger"
msgid "SSHFP - SSH Public Key Fingerprint"
msgstr "SSHFP - SSH Fingerprint für öffentlichen Schlüssel"
msgid "Select an IP"
msgstr "Wähle eine IP"
msgid "Serial"
msgstr "Seriennummer"
msgid "TTL"
msgstr "TTL"
msgid "TTL (seconds)"
msgstr "TTL (Sekunden)"
msgid "TXT"
msgstr "TXT"
msgid "TXT - Text record"
msgstr "TXT - Text Datensatz"
msgid "Text"
msgstr "Text"
msgid "The quotas could not be retrieved."
msgstr "Die Kontingente konnten nicht abgerufen werden."
msgid "There are no floating IP addresses currently in use to select from."
msgstr "Es stehen derzeit keine Floating IP-Adressen zur Auswahl."
msgid "This field is required"
msgstr "Dieses Feld ist erforderlich"
msgid "Type"
msgstr "Typ"
msgid "Unable to create domain."
msgstr "Die Domäne kann nicht erstellt werden."
msgid "Unable to create record."
msgstr "Datensatz konnte nicht erzeugt werden."
msgid "Unable to retrieve domain list."
msgstr "Domänen-Liste kann nicht abgerufen werden."
msgid "Unable to retrieve domain record."
msgstr "Domänendatensatz kann nicht abgerufen werden."
msgid "Unable to retrieve record list."
msgstr "Die Datensatzliste kann nicht abgerufen werden."
msgid "Unable to update domain."
msgstr "Die Domäne kann nicht geändert werden."
msgid "Unknown"
msgstr "Unbekannt"
msgid "Unknown instance name"
msgstr "Unbekannter Instanzname"
msgid "Update Domain"
msgstr "Domain ändern"
msgid "Update Domain Record"
msgstr "Domänendatensatz aktualisieren"
msgid "Update Record"
msgstr "Datensatz aktualisieren"
msgid "Updated"
msgstr "Aktualisiert"
msgid "Updated At"
msgstr "Aktualisiert am"
msgid "Value"
msgstr "Wert"
msgid "Zones"
msgstr "Zonen"

Binary file not shown.

View File

@ -0,0 +1,351 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
# Rob Cresswell <robert.cresswell@outlook.com>, 2015. #zanata
# Andi Chandler <andi@gowling.com>, 2016. #zanata
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
msgid ""
msgstr ""
"Project-Id-Version: designate-dashboard 3.0.0.0rc2.dev6\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2016-10-14 10:51+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2016-10-23 09:03+0000\n"
"Last-Translator: Andreas Jaeger <jaegerandi@gmail.com>\n"
"Language-Team: English (United Kingdom)\n"
"Language: en-GB\n"
"X-Generator: Zanata 3.7.3\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
msgid ""
"\n"
" From here you can edit the email address and TTL associated with a "
"domain.\n"
" "
msgstr ""
"\n"
" From here you can edit the email address and TTL associated with a "
"domain.\n"
" "
msgid ""
"\n"
" The Email field should contain a valid email address to be associated\n"
" with the domain.\n"
" "
msgstr ""
"\n"
" The Email field should contain a valid email address to be associated\n"
" with the domain.\n"
" "
msgid ""
"\n"
" The Name field should contain a full-qualified domain name (with\n"
" trailing period).\n"
" "
msgstr ""
"\n"
" The Name field should contain a full-qualified domain name (with\n"
" trailing period).\n"
" "
msgid ""
"\n"
" The optional TTL field can be any value between 1 and 2147483647\n"
" seconds.\n"
" "
msgstr ""
"\n"
" The optional TTL field can be any value between 1 and 2147483647\n"
" seconds.\n"
" "
msgid ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" The TTL is the time-to-live for the record, in seconds.\n"
" </p>\n"
" <p>\n"
" See <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">more info</a> on record types.\n"
" </p>\n"
" "
msgstr ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" The TTL is the time-to-live for the record, in seconds.\n"
" </p>\n"
" <p>\n"
" See <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">more info</a> on record types.\n"
" </p>\n"
" "
msgid "A - Address record"
msgstr "A - Address record"
msgid "AAAA - IPv6 address record"
msgstr "AAAA - IPv6 address record"
msgid "All Records"
msgstr "All Records"
msgid "CNAME - Canonical name record"
msgstr "CNAME - Canonical name record"
msgid "Cancel"
msgstr "Cancel"
msgid "Canonical Name"
msgstr "Canonical Name"
msgid "Create Domain"
msgstr "Create Domain"
msgid "Create Domain Record"
msgstr "Create Domain Record"
msgid "Create Record"
msgstr "Create Record"
msgid "Create Record for"
msgstr "Create Record for"
msgid "Created"
msgstr "Created"
msgid "Created At"
msgstr "Created At"
msgid "Data"
msgstr "Data"
msgid "Delete"
msgstr "Delete"
msgid "Deleted"
msgstr "Deleted"
msgid "Description"
msgstr "Description"
msgid "Domain"
msgstr "Domain"
#, python-format
msgid "Domain %(name)s created."
msgstr "Domain %(name)s created."
#, python-format
msgid "Domain %(name)s updated."
msgstr "Domain %(name)s updated."
msgid "Domain Detail"
msgstr "Domain Detail"
msgid "Domain Name"
msgstr "Domain Name"
msgid "Domain Overview"
msgstr "Domain Overview"
msgid "Domain Records"
msgstr "Domain Records"
#, python-format
msgid "Domain record %(name)s created."
msgstr "Domain record %(name)s created."
#, python-format
msgid "Domain record %(name)s updated."
msgstr "Domain record %(name)s updated."
msgid "Domains"
msgstr "Domains"
msgid "Edit Domain"
msgstr "Edit Domain"
msgid "Edit Record"
msgstr "Edit Record"
msgid "Email"
msgstr "Email"
msgid "Enter a valid IPv4 address"
msgstr "Enter a valid IPv4 address"
msgid "Enter a valid IPv6 address"
msgstr "Enter a valid IPv6 address"
msgid "Enter a valid SRV name"
msgstr "Enter a valid SRV name"
msgid "Enter a valid SRV record"
msgstr "Enter a valid SRV record"
msgid "Enter a valid SSHFP record"
msgstr "Enter a valid SSHFP record"
msgid "Enter a valid domain name."
msgstr "Enter a valid domain name."
msgid "Enter a valid hostname"
msgstr "Enter a valid hostname"
msgid ""
"Enter a valid hostname. The hostname should contain letters and numbers, and "
"be no more than 63 characters."
msgstr ""
"Enter a valid hostname. The hostname should contain letters and numbers, and "
"be no more than 63 characters."
msgid "ID"
msgstr "ID"
msgid "IP Address"
msgstr "IP Address"
msgid "MX - Mail exchange record"
msgstr "MX - Mail exchange record"
msgid "Mail Server"
msgstr "Mail Server"
msgid "Manage Records"
msgstr "Manage Records"
msgid "NS"
msgstr "NS"
msgid "Name"
msgstr "Name"
msgid "Name Server"
msgstr "Name Server"
msgid "Nameservers"
msgstr "Nameservers"
msgid "None"
msgstr "None"
msgid "PTR - Pointer record"
msgstr "PTR - Pointer record"
msgid "PTR Domain Name"
msgstr "PTR Domain Name"
msgid "Priority"
msgstr "Priority"
msgid "Record"
msgstr "Record"
msgid "Record Data"
msgstr "Record Data"
msgid "Record Detail"
msgstr "Record Detail"
msgid "Record Type"
msgstr "Record Type"
msgid "Records"
msgstr "Records"
msgid "Reverse DNS"
msgstr "Reverse DNS"
msgid "SOA"
msgstr "SOA"
msgid "SPF - Sender Policy Framework"
msgstr "SPF - Sender Policy Framework"
msgid "SRV - Service locator"
msgstr "SRV - Service locator"
msgid "SSHFP - SSH Public Key Fingerprint"
msgstr "SSHFP - SSH Public Key Fingerprint"
msgid "Select an IP"
msgstr "Select an IP"
msgid "Serial"
msgstr "Serial"
msgid "TTL"
msgstr "TTL"
msgid "TTL (seconds)"
msgstr "TTL (seconds)"
msgid "TXT"
msgstr "TXT"
msgid "TXT - Text record"
msgstr "TXT - Text record"
msgid "Text"
msgstr "Text"
msgid "The quotas could not be retrieved."
msgstr "The quotas could not be retrieved."
msgid "There are no floating IP addresses currently in use to select from."
msgstr "There are no floating IP addresses currently in use to select from."
msgid "This field is required"
msgstr "This field is required"
msgid "Type"
msgstr "Type"
msgid "Unable to create domain."
msgstr "Unable to create domain."
msgid "Unable to create record."
msgstr "Unable to create record."
msgid "Unable to retrieve domain list."
msgstr "Unable to retrieve domain list."
msgid "Unable to retrieve domain record."
msgstr "Unable to retrieve domain record."
msgid "Unable to retrieve record list."
msgstr "Unable to retrieve record list."
msgid "Unable to update domain."
msgstr "Unable to update domain."
msgid "Unknown"
msgstr "Unknown"
msgid "Unknown instance name"
msgstr "Unknown instance name"
msgid "Update Domain"
msgstr "Update Domain"
msgid "Update Domain Record"
msgstr "Update Domain Record"
msgid "Update Record"
msgstr "Update Record"
msgid "Updated"
msgstr "Updated"
msgid "Updated At"
msgstr "Updated At"
msgid "Value"
msgstr "Value"
msgid "Zones"
msgstr "Zones"

Binary file not shown.

View File

@ -0,0 +1,342 @@
# Marian Tort <marian.tort@gmail.com>, 2015. #zanata
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# Eugènia Torrella <tester03@es.ibm.com>, 2016. #zanata
# Alberto Molina Coballes <alb.molina@gmail.com>, 2017. #zanata
# Zeus Arias Lucero <zeusariaslucero@gmail.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: designate-dashboard 5.0.0.0rc2.dev4\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-08-23 14:30+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-08-24 09:39+0000\n"
"Last-Translator: Zeus Arias Lucero <zeusariaslucero@gmail.com>\n"
"Language-Team: Spanish\n"
"Language: es\n"
"X-Generator: Zanata 3.9.6\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
msgid ""
"\n"
" From here you can edit the email address and TTL associated with a "
"domain.\n"
" "
msgstr ""
"\n"
" Desde aquí puede editar la dirección de correo y el TTL asociado a un "
"dominio.\n"
" "
msgid ""
"\n"
" The Name field should contain a full-qualified domain name (with\n"
" trailing period).\n"
" "
msgstr ""
"\n"
" El campo nombre debe contener un full-qualified domain name (con \n"
" punto final).\n"
" "
msgid ""
"\n"
" The optional TTL field can be any value between 1 and 2147483647\n"
" seconds.\n"
" "
msgstr ""
"\n"
" El campo opcional TTL puede tener un valor entre 1 y 2147483647\n"
" segundos.\n"
" "
msgid ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" The TTL is the time-to-live for the record, in seconds.\n"
" </p>\n"
" <p>\n"
" See <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">more info</a> on record types.\n"
" </p>\n"
" "
msgstr ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" El TTL es el tiempo de vida del registro en segundos.\n"
" </p>\n"
" <p>\n"
" Vea <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">más info</a> sobre tipos de registros.\n"
" </p>\n"
" "
msgid "A - Address record"
msgstr "A - Registro de dirección IPv4"
msgid "AAAA - IPv6 address record"
msgstr "AAAA - Registro de dirección IPv6"
msgid "All Records"
msgstr "Todos los registros"
msgid "CNAME - Canonical name record"
msgstr "CNAME - Registro de nombre canónico"
msgid "Cancel"
msgstr "Cancelar "
msgid "Canonical Name"
msgstr "Nombre canónico"
msgid "Create Domain"
msgstr "Crear dominio"
msgid "Create Domain Record"
msgstr "Crear registro del dominio"
msgid "Create Record"
msgstr "Crear registro"
msgid "Create Record for"
msgstr "Crear registro para"
msgid "Created"
msgstr "Creado"
msgid "Created At"
msgstr "Creado el"
msgid "Data"
msgstr "Datos"
msgid "Delete"
msgstr "Eliminar"
msgid "Deleted"
msgstr "Eliminado"
msgid "Description"
msgstr "Descripción"
msgid "Domain"
msgstr "Dominio"
#, python-format
msgid "Domain %(name)s created."
msgstr "Dominio %(name)s creado."
#, python-format
msgid "Domain %(name)s updated."
msgstr "Dominio %(name)s actualizado."
msgid "Domain Detail"
msgstr "Detalles del dominio"
msgid "Domain Name"
msgstr "Nombre de dominio"
msgid "Domain Overview"
msgstr "Visión general del dominio"
msgid "Domain Records"
msgstr "Registros del dominio"
#, python-format
msgid "Domain record %(name)s created."
msgstr "Registro de dominio %(name)s creado"
#, python-format
msgid "Domain record %(name)s updated."
msgstr "Registro de dominio %(name)s actualizado"
msgid "Domains"
msgstr "Dominios"
msgid "Edit Domain"
msgstr "Editar dominio"
msgid "Edit Record"
msgstr "Editar registro"
msgid "Email"
msgstr "Correo electrónico"
msgid "Enter a valid IPv4 address"
msgstr "Introduzca una dirección IPv4 válida"
msgid "Enter a valid IPv6 address"
msgstr "Introduzca una dirección IPv6 válida"
msgid "Enter a valid SRV name"
msgstr "Introduzca un nombre SRV válido"
msgid "Enter a valid SRV record"
msgstr "Introduzca un registro SRV válido"
msgid "Enter a valid SSHFP record"
msgstr "Introduzca un registro SSHFP válido"
msgid "Enter a valid domain name."
msgstr "Introduzca un nombre de dominio válido."
msgid "Enter a valid hostname"
msgstr "Introduzca un hostname válido"
msgid ""
"Enter a valid hostname. The hostname should contain letters and numbers, and "
"be no more than 63 characters."
msgstr ""
"Introduzca un hostname válido. El hostname puede incluir letras, números y "
"no tener más de 63 caracteres."
msgid "ID"
msgstr "ID"
msgid "IP Address"
msgstr "Dirección IP"
msgid "MX - Mail exchange record"
msgstr "MX - Registro de Mail exchange"
msgid "Mail Server"
msgstr "Servidor de correo"
msgid "Manage Records"
msgstr "Gestionar registros"
msgid "NS"
msgstr "NS"
msgid "Name"
msgstr "Nombre"
msgid "Name Server"
msgstr "Servidor de nombres"
msgid "Nameservers"
msgstr "Servidores de nombres"
msgid "None"
msgstr "Ninguno"
msgid "PTR - Pointer record"
msgstr "PTR - Registro de puntero"
msgid "PTR Domain Name"
msgstr "Nombre de dominio PTR"
msgid "Priority"
msgstr "Prioridad"
msgid "Record"
msgstr "Registro"
msgid "Record Data"
msgstr "Registro"
msgid "Record Detail"
msgstr "Detalles del registro"
msgid "Record Type"
msgstr "Tipo de registro"
msgid "Records"
msgstr "Registros"
msgid "Reverse DNS"
msgstr "DNS inverso"
msgid "SOA"
msgstr "SOA"
msgid "SPF - Sender Policy Framework"
msgstr "SPF - Sender Policy Framework"
msgid "SRV - Service locator"
msgstr "SRV - Servicio locator"
msgid "SSHFP - SSH Public Key Fingerprint"
msgstr "SSHFP - Huella digital de clave SSH pública"
msgid "Select an IP"
msgstr "Seleccione una IP"
msgid "Serial"
msgstr "Serial"
msgid "TTL"
msgstr "TTL"
msgid "TTL (seconds)"
msgstr "TTL (segundos)"
msgid "TXT"
msgstr "TXT"
msgid "TXT - Text record"
msgstr "TXT - Registro de texto"
msgid "Text"
msgstr "Texto"
msgid "The quotas could not be retrieved."
msgstr "No ha sido posible obtener las cuotas."
msgid "There are no floating IP addresses currently in use to select from."
msgstr "Actualmente no hay direcciones IP flotantes en uso para seleccionar."
msgid "This field is required"
msgstr "Este campo es obligatorio"
msgid "Type"
msgstr "Tipo"
msgid "Unable to create domain."
msgstr "No ha sido posible crear el dominio."
msgid "Unable to create record."
msgstr "No ha sido posible crear el registro."
msgid "Unable to retrieve domain list."
msgstr "No ha sido posible obtener la lista de dominios."
msgid "Unable to retrieve domain record."
msgstr "No ha sido posible obtener el registro del dominio."
msgid "Unable to retrieve record list."
msgstr "No ha sido posible obtener la lista de registros."
msgid "Unable to update domain."
msgstr "No ha sido posible actualizar el dominio."
msgid "Unknown"
msgstr "Desconocido"
msgid "Unknown instance name"
msgstr "Nombre de instancia desconicodo"
msgid "Update Domain"
msgstr "Actualizar dominio"
msgid "Update Domain Record"
msgstr "Actualizar registro del dominio"
msgid "Update Record"
msgstr "Actualizar registro"
msgid "Updated"
msgstr "Actualizada"
msgid "Updated At"
msgstr "Actualizado el"
msgid "Value"
msgstr "Valor"
msgid "Zones"
msgstr "Zonas"

Binary file not shown.

View File

@ -0,0 +1,362 @@
# Translations template for designate-dashboard.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the designate-dashboard
# project.
#
# Translators:
# Lucas Mascaro <mascaro.lucas@yahoo.fr>, 2015
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# Gael Rehault <gael_rehault@dell.com>, 2016. #zanata
# Gérald LONLAS <g.lonlas@gmail.com>, 2016. #zanata
# Gaelle <pattedeph@gmail.com>, 2017. #zanata
# JF Taltavull <jftalta@gmail.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: designate-dashboard 6.0.0.0b2.dev3\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-11-21 15:00+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-11-14 07:52+0000\n"
"Last-Translator: Gaelle <pattedeph@gmail.com>\n"
"Language: fr\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.9.6\n"
"Language-Team: French\n"
msgid ""
"\n"
" From here you can edit the email address and TTL associated with a "
"domain.\n"
" "
msgstr ""
"\n"
" Ici vous pouvez éditer l'adresse email e t le TTL associés à un "
"domaine.\n"
" "
msgid ""
"\n"
" The Email field should contain a valid email address to be associated\n"
" with the domain.\n"
" "
msgstr ""
"\n"
" Le champ Email doit contenir un email valide qui sera associé \n"
" avec le domaine.\n"
" "
msgid ""
"\n"
" The Name field should contain a full-qualified domain name (with\n"
" trailing period).\n"
" "
msgstr ""
"\n"
" Le champ Nom doit contenir un nom de domaine (FQDN avec le\n"
" point \".\" de terminaison).\n"
" "
msgid ""
"\n"
" The optional TTL field can be any value between 1 and 2147483647\n"
" seconds.\n"
" "
msgstr ""
"\n"
" La valeur du champ optionnel TTL doit être comprise entre 1 et "
"2147483647\n"
" secondes.\n"
" "
msgid ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" The TTL is the time-to-live for the record, in seconds.\n"
" </p>\n"
" <p>\n"
" See <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">more info</a> on record types.\n"
" </p>\n"
" "
msgstr ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" Le TTL est le time-to-live de l'enregistrement, en secondes.\n"
" </p>\n"
" <p>\n"
" Voir <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">plus de détails</a> sur les types "
"d'enregistrement.\n"
" </p>\n"
" "
msgid "A - Address record"
msgstr "A - Enregistrement d'Adresse"
msgid "AAAA - IPv6 address record"
msgstr "AAAA - Enregistrement d'Adresse IPv6"
msgid "All Records"
msgstr "Tous les enregistrements"
msgid "CNAME - Canonical name record"
msgstr "CNAME - Enregistrement de Nom Canonique"
msgid "Cancel"
msgstr "Annuler"
msgid "Canonical Name"
msgstr "Nom canonique"
msgid "Create Domain"
msgstr "Créer un domaine"
msgid "Create Domain Record"
msgstr "Créer un enregistrement de domaine"
msgid "Create Record"
msgstr "Créer un enregistrement"
msgid "Create Record for"
msgstr "Créer un enregistrement pour"
msgid "Created"
msgstr "Créé"
msgid "Created At"
msgstr "Créé le"
msgid "Data"
msgstr "Données"
msgid "Delete"
msgstr "Supprimer"
msgid "Deleted"
msgstr "Supprimé"
msgid "Description"
msgstr "Description"
msgid "Domain"
msgstr "Domaine"
#, python-format
msgid "Domain %(name)s created."
msgstr "Domaine %(name)s créé."
#, python-format
msgid "Domain %(name)s updated."
msgstr "Domaine %(name)s mis à jour."
msgid "Domain Detail"
msgstr "Détail du domaine"
msgid "Domain Name"
msgstr "Nom de domaine"
msgid "Domain Overview"
msgstr "Vue d'ensemble du domaine"
msgid "Domain Records"
msgstr "Enregistrements de domaine"
#, python-format
msgid "Domain record %(name)s created."
msgstr "Enregistrement Domaine %(name)s créé"
#, python-format
msgid "Domain record %(name)s updated."
msgstr "Enregistrement Domaine %(name)s mis à jour."
msgid "Domains"
msgstr "Domaines"
msgid "Edit Domain"
msgstr "Editer le domaine"
msgid "Edit Record"
msgstr "Editer l'enregistrement"
msgid "Email"
msgstr "Courriel"
msgid "Enter a valid IPv4 address"
msgstr "Entrer une adresse IPv4 valide"
msgid "Enter a valid IPv6 address"
msgstr "Entrer une adresse IPv6 valide"
msgid "Enter a valid SRV name"
msgstr "Entrer un nom SRV valide"
msgid "Enter a valid SRV record"
msgstr "Entrer un enregistrement SRV valide"
msgid "Enter a valid SSHFP record"
msgstr "Entrer un enregistrement SSHFP valide"
msgid "Enter a valid domain name."
msgstr "Entrer un nom de domaine valide."
msgid "Enter a valid hostname"
msgstr "Entrer un nom d'hôte valide"
msgid ""
"Enter a valid hostname. The hostname should contain letters and numbers, and "
"be no more than 63 characters."
msgstr ""
"Entrer un nom d'hôte valide. Le nom d'hôte ne doit contenir que des lettres "
"et des chiffres, et ne doit pas dépasser 63 caractères."
msgid "ID"
msgstr "ID"
msgid "IP Address"
msgstr "Adresse IP"
msgid "MX - Mail exchange record"
msgstr "MX - Enregistrement de Serveur de messagerie"
msgid "Mail Server"
msgstr "Serveur de messagerie"
msgid "Manage Records"
msgstr "Gérer les enregistrements"
msgid "NS"
msgstr "NS"
msgid "Name"
msgstr "Nom"
msgid "Name Server"
msgstr "Nom de serveur"
msgid "Nameservers"
msgstr "Serveurs de nom"
msgid "None"
msgstr "Aucun"
msgid "PTR - Pointer record"
msgstr "PTR - Enregistrement de Pointeur"
msgid "PTR Domain Name"
msgstr "Nom de domaine PTR"
msgid "Priority"
msgstr "Priorité"
msgid "Record"
msgstr "Enregistrement"
msgid "Record Data"
msgstr "Enregistrer les données"
msgid "Record Detail"
msgstr "Détail de l'enregistrement"
msgid "Record Type"
msgstr "Type d'enregistrement"
msgid "Records"
msgstr "Enregistrements"
msgid "Reverse DNS"
msgstr "Reverse DNS"
msgid "SOA"
msgstr "SOA"
msgid "SPF - Sender Policy Framework"
msgstr "SPF - Politique démission"
msgid "SRV - Service locator"
msgstr "SRV - Enregistrement de Service"
msgid "SSHFP - SSH Public Key Fingerprint"
msgstr "SSHFP - Somme de contrôle de la clé SSH publique"
msgid "Select an IP"
msgstr "Sélectionner une IP"
msgid "Serial"
msgstr "Numéro de série"
msgid "TTL"
msgstr "TTL"
msgid "TTL (seconds)"
msgstr "TTL (secondes)"
msgid "TXT"
msgstr "TXT"
msgid "TXT - Text record"
msgstr "TXT - Enregistrement Texte"
msgid "Text"
msgstr "Texte"
msgid "The quotas could not be retrieved."
msgstr "Les quotas n'ont pas pu être récupérés."
msgid "There are no floating IP addresses currently in use to select from."
msgstr "Aucune adresse IP flottante en cours d'utilisation à sélectionner."
msgid "This field is required"
msgstr "Ce champ est requis"
msgid "Type"
msgstr "Type"
msgid "Unable to create domain."
msgstr "Impossible de créer le domaine."
msgid "Unable to create record."
msgstr "Impossible de créer un enregistrement"
msgid "Unable to retrieve domain list."
msgstr "Impossible de récupérer la liste des domaines."
msgid "Unable to retrieve domain record."
msgstr "Impossible de récupérer l'enregistrement de domaine."
msgid "Unable to retrieve record list."
msgstr "Impossible de récupérer la liste des enregistrements."
msgid "Unable to update domain."
msgstr "Impossible de mettre à jour le domaine."
msgid "Unknown"
msgstr "Inconnu"
msgid "Unknown instance name"
msgstr "Nom d'instance inconnu"
msgid "Update Domain"
msgstr "Mettre à jour le domaine"
msgid "Update Domain Record"
msgstr "Mettre à jour l'enregistrement de domaine"
msgid "Update Record"
msgstr "Mettre à jour l'enregistrement"
msgid "Updated"
msgstr "Mis à jour"
msgid "Updated At"
msgstr "Mis à jour le"
msgid "Value"
msgstr "Valeur"
msgid "Zones"
msgstr "Zones"

Binary file not shown.

View File

@ -0,0 +1,350 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# suhartono <cloudsuhartono@gmail.com>, 2016. #zanata
msgid ""
msgstr ""
"Project-Id-Version: designate-dashboard 3.0.0.0rc2.dev5\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2016-09-29 13:19+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2016-10-13 04:32+0000\n"
"Last-Translator: suhartono <cloudsuhartono@gmail.com>\n"
"Language-Team: Indonesian\n"
"Language: id\n"
"X-Generator: Zanata 3.7.3\n"
"Plural-Forms: nplurals=1; plural=0\n"
msgid ""
"\n"
" From here you can edit the email address and TTL associated with a "
"domain.\n"
" "
msgstr ""
"\n"
" Dari sini Anda dapat mengedit alamat email dan TTL terkait dengan "
"domain.\n"
" "
msgid ""
"\n"
" The Email field should contain a valid email address to be associated\n"
" with the domain.\n"
" "
msgstr ""
"\n"
"Kolom email harus berisi alamat email yang valid terkait\n"
"       dengan domain.\n"
" "
msgid ""
"\n"
" The Name field should contain a full-qualified domain name (with\n"
" trailing period).\n"
" "
msgstr ""
"\n"
" The Name field should contain a full-qualified domain name (with\n"
" trailing period).\n"
" "
msgid ""
"\n"
" The optional TTL field can be any value between 1 and 2147483647\n"
" seconds.\n"
" "
msgstr ""
"\n"
" Kolom TTL opsional dapat berupa nilai antara 1 dan 2147483647\n"
" detik.\n"
" "
msgid ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" The TTL is the time-to-live for the record, in seconds.\n"
" </p>\n"
" <p>\n"
" See <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">more info</a> on record types.\n"
" </p>\n"
" "
msgstr ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" TTL adalah time-to-live untuk rekor, dalam hitungan detik.\n"
" </p>\n"
" <p>\n"
" Lihat <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">more info</a> pada tipe rekor.\n"
" </p>\n"
" "
msgid "A - Address record"
msgstr "A - Address record"
msgid "AAAA - IPv6 address record"
msgstr "AAAA - IPv6 address record"
msgid "All Records"
msgstr "All Records (semua rekor)"
msgid "CNAME - Canonical name record"
msgstr "CNAME - Canonical name record"
msgid "Cancel"
msgstr "Batal"
msgid "Canonical Name"
msgstr "Canonical Name (nama canonical)"
msgid "Create Domain"
msgstr "Membuat Domain"
msgid "Create Domain Record"
msgstr "Create Domain Record (buat rekor domain)"
msgid "Create Record"
msgstr "Buat rekor"
msgid "Create Record for"
msgstr "Buat rekor"
msgid "Created"
msgstr "Created (dibuat)"
msgid "Created At"
msgstr "Created At (dibuat pada)"
msgid "Data"
msgstr "Data"
msgid "Delete"
msgstr "Hapus"
msgid "Deleted"
msgstr "Terhapus"
msgid "Description"
msgstr "Deskripsi"
msgid "Domain"
msgstr "Domain"
#, python-format
msgid "Domain %(name)s created."
msgstr "Domain %(name)s dibuat."
#, python-format
msgid "Domain %(name)s updated."
msgstr "Domain %(name)s diperbaharui."
msgid "Domain Detail"
msgstr "Domain Detail (rincian domain)"
msgid "Domain Name"
msgstr "Nama domain"
msgid "Domain Overview"
msgstr "Domain Overview (ikhtisar domain)"
msgid "Domain Records"
msgstr "Domain Records (rekor domain)"
#, python-format
msgid "Domain record %(name)s created."
msgstr "Rekor domain %(name)s dibuat."
#, python-format
msgid "Domain record %(name)s updated."
msgstr "Rekor domain %(name)s diperbaharui"
msgid "Domains"
msgstr "Domain"
msgid "Edit Domain"
msgstr "Mengedit domain"
msgid "Edit Record"
msgstr "Mengedit recor"
msgid "Email"
msgstr "Surat elektronik"
msgid "Enter a valid IPv4 address"
msgstr "Masukkan alamat IPv4 yang valid"
msgid "Enter a valid IPv6 address"
msgstr "Masukkan alamat IPv6 yang valid"
msgid "Enter a valid SRV name"
msgstr "Masukkan nama SRV valid"
msgid "Enter a valid SRV record"
msgstr "Masukkan rekor SRV valid"
msgid "Enter a valid SSHFP record"
msgstr "Masukkan rekor SSHFP valid"
msgid "Enter a valid domain name."
msgstr "Masukkan nama domain yang valid."
msgid "Enter a valid hostname"
msgstr "Masukkan hostname yang valid"
msgid ""
"Enter a valid hostname. The hostname should contain letters and numbers, and "
"be no more than 63 characters."
msgstr ""
"Masukkan hostname yang valid. Hostname harus berisi huruf dan angka, dan "
"tidak lebih dari 63 karakter."
msgid "ID"
msgstr "ID"
msgid "IP Address"
msgstr "IP Address (alamat IP)"
msgid "MX - Mail exchange record"
msgstr "MX - Mail exchange record"
msgid "Mail Server"
msgstr "Mail Server (server mail)"
msgid "Manage Records"
msgstr "Mengelola rekor"
msgid "NS"
msgstr "NS"
msgid "Name"
msgstr "Name (nama)"
msgid "Name Server"
msgstr "Name Server (server nama)"
msgid "Nameservers"
msgstr "Nameservers"
msgid "None"
msgstr "None (tak satupun)"
msgid "PTR - Pointer record"
msgstr "PTR - Pointer record"
msgid "PTR Domain Name"
msgstr "PTR Domain Name (nama domain PTR)"
msgid "Priority"
msgstr "Priority (prioritas)"
msgid "Record"
msgstr "Record (rekor)"
msgid "Record Data"
msgstr "Record Data (data rekam)"
msgid "Record Detail"
msgstr "Record Detail (rincian rekor)"
msgid "Record Type"
msgstr "Record Type (tipe rekam)"
msgid "Records"
msgstr "Records (rekor)"
msgid "Reverse DNS"
msgstr "Reverse DNS "
msgid "SOA"
msgstr "SOA"
msgid "SPF - Sender Policy Framework"
msgstr "SPF - Sender Policy Framework"
msgid "SRV - Service locator"
msgstr "SRV - Service locator"
msgid "SSHFP - SSH Public Key Fingerprint"
msgstr "SSHFP - SSH Public Key Fingerprint"
msgid "Select an IP"
msgstr "Pilih IP"
msgid "Serial"
msgstr "Serial (serial)"
msgid "TTL"
msgstr "TTL"
msgid "TTL (seconds)"
msgstr "TTL (detik)"
msgid "TXT"
msgstr "TXT"
msgid "TXT - Text record"
msgstr "TXT - Text record"
msgid "Text"
msgstr "Text"
msgid "The quotas could not be retrieved."
msgstr "Kuota tidak dapat diambil."
msgid "There are no floating IP addresses currently in use to select from."
msgstr "Tidak ada alamat IP mengambang saat ini yang digunakan untuk memilih."
msgid "This field is required"
msgstr "Bagian ini diperlukan"
msgid "Type"
msgstr "Tipe"
msgid "Unable to create domain."
msgstr "Tidak dapat membuat domain."
msgid "Unable to create record."
msgstr "Tidak dapat membuat rekor."
msgid "Unable to retrieve domain list."
msgstr "Tidak dapat mengambil daftar domain."
msgid "Unable to retrieve domain record."
msgstr "Tidak dapat mengambil rekor domain."
msgid "Unable to retrieve record list."
msgstr "Tidak dapat mengambil daftar rekor."
msgid "Unable to update domain."
msgstr "Tidak dapat memperbarui domain."
msgid "Unknown"
msgstr "Unknown (tidak diketahui)"
msgid "Unknown instance name"
msgstr " nama instance tidak diketahui"
msgid "Update Domain"
msgstr "Update Domain (pembaharui domain)"
msgid "Update Domain Record"
msgstr "Update Domain Record (pembaharuan rekor domain)"
msgid "Update Record"
msgstr "Pembaruan rekor"
msgid "Updated"
msgstr "Updated (sudah di perbaharui)"
msgid "Updated At"
msgstr "Diperbarui pada"
msgid "Value"
msgstr "Value (nilai)"
msgid "Zones"
msgstr "Zones (zona)"

Binary file not shown.

View File

@ -0,0 +1,347 @@
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# Mie Yamamoto <myamamot@redhat.com>, 2016. #zanata
# Yoshiki Eguchi <yoshiki.eguchi@gmail.com>, 2016. #zanata
msgid ""
msgstr ""
"Project-Id-Version: designate-dashboard 3.0.0.0rc2.dev5\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2016-09-29 13:19+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2016-10-13 04:32+0000\n"
"Last-Translator: Akihiro Motoki <amotoki@gmail.com>\n"
"Language-Team: Japanese\n"
"Language: ja\n"
"X-Generator: Zanata 3.7.3\n"
"Plural-Forms: nplurals=1; plural=0\n"
msgid ""
"\n"
" From here you can edit the email address and TTL associated with a "
"domain.\n"
" "
msgstr ""
"\n"
" ここでドメインに関連付けられたメールアドレスと TTL を編集できます。\n"
" "
msgid ""
"\n"
" The Email field should contain a valid email address to be associated\n"
" with the domain.\n"
" "
msgstr ""
"\n"
" メールフィールドには、ドメインに関連付ける\n"
" 有効なメールアドレスを指定する必要があります。\n"
" "
msgid ""
"\n"
" The Name field should contain a full-qualified domain name (with\n"
" trailing period).\n"
" "
msgstr ""
"\n"
" 名前フィールドには、\n"
" (末尾がピリオドの) 完全修飾ドメイン名を指定する必要があります。\n"
" "
msgid ""
"\n"
" The optional TTL field can be any value between 1 and 2147483647\n"
" seconds.\n"
" "
msgstr ""
"\n"
" オプションの TTL フィールドは\n"
" 1 秒から 2147483647 秒までの任意の値にできます。\n"
" "
msgid ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" The TTL is the time-to-live for the record, in seconds.\n"
" </p>\n"
" <p>\n"
" See <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">more info</a> on record types.\n"
" </p>\n"
" "
msgstr ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" TTL はこのレコードの生存時間 (time-to-live) で、単位は秒です。\n"
" </p>\n"
" <p>\n"
" レコードタイプの詳細は<a href=\"http://en.wikipedia.org/wiki/"
"List_of_DNS_record_types\" target=\"_designate_record_defs\">こちら</a>を参照"
"してください。\n"
" </p>\n"
" "
msgid "A - Address record"
msgstr "A - アドレスレコード"
msgid "AAAA - IPv6 address record"
msgstr "AAAA - IPv6 アドレスレコード"
msgid "All Records"
msgstr "全レコード"
msgid "CNAME - Canonical name record"
msgstr "CNAME - 別名レコード"
msgid "Cancel"
msgstr "取り消し"
msgid "Canonical Name"
msgstr "正規名"
msgid "Create Domain"
msgstr "ドメインの作成"
msgid "Create Domain Record"
msgstr "ドメインレコードの作成"
msgid "Create Record"
msgstr "レコードの作成"
msgid "Create Record for"
msgstr "レコードの作成: ドメイン"
msgid "Created"
msgstr "作成時刻"
msgid "Created At"
msgstr "作成時刻"
msgid "Data"
msgstr "データ"
msgid "Delete"
msgstr "削除"
msgid "Deleted"
msgstr "削除"
msgid "Description"
msgstr "説明"
msgid "Domain"
msgstr "ドメイン"
#, python-format
msgid "Domain %(name)s created."
msgstr "ドメイン %(name)s が作成されました。"
#, python-format
msgid "Domain %(name)s updated."
msgstr "ドメイン %(name)s が更新されました。"
msgid "Domain Detail"
msgstr "ドメインの詳細"
msgid "Domain Name"
msgstr "ドメイン名"
msgid "Domain Overview"
msgstr "ドメインの概要"
msgid "Domain Records"
msgstr "ドメインレコード"
#, python-format
msgid "Domain record %(name)s created."
msgstr "ドメインレコード %(name)s が作成されました。"
#, python-format
msgid "Domain record %(name)s updated."
msgstr "ドメインレコード %(name)s が更新されました。"
msgid "Domains"
msgstr "ドメイン"
msgid "Edit Domain"
msgstr "ドメインの編集"
msgid "Edit Record"
msgstr "レコードの編集"
msgid "Email"
msgstr "メール"
msgid "Enter a valid IPv4 address"
msgstr "有効な IPv4 アドレスを入力してください。"
msgid "Enter a valid IPv6 address"
msgstr "有効な IPv6 アドレスを入力してください。"
msgid "Enter a valid SRV name"
msgstr "有効な SRV 名を入力してください。"
msgid "Enter a valid SRV record"
msgstr "有効な SRV レコードを入力してください。"
msgid "Enter a valid SSHFP record"
msgstr "有効な SSHFP レコードを入力してください。"
msgid "Enter a valid domain name."
msgstr "有効なドメイン名を入力してください。"
msgid "Enter a valid hostname"
msgstr "有効なホスト名を入力してください。"
msgid ""
"Enter a valid hostname. The hostname should contain letters and numbers, and "
"be no more than 63 characters."
msgstr ""
"有効なホスト名を入力してください。ホスト名は、文字と数字で 63 文字以内に設定"
"してください。"
msgid "ID"
msgstr "ID"
msgid "IP Address"
msgstr "IP アドレス"
msgid "MX - Mail exchange record"
msgstr "MX - Mail exchange レコード"
msgid "Mail Server"
msgstr "メールサーバー"
msgid "Manage Records"
msgstr "レコードの管理"
msgid "NS"
msgstr "NS"
msgid "Name"
msgstr "名前"
msgid "Name Server"
msgstr "ネームサーバー"
msgid "Nameservers"
msgstr "ネームサーバー"
msgid "None"
msgstr "なし"
msgid "PTR - Pointer record"
msgstr "PTR - ポインターレコード"
msgid "PTR Domain Name"
msgstr "PTR ドメイン名"
msgid "Priority"
msgstr "優先度"
msgid "Record"
msgstr "レコード"
msgid "Record Data"
msgstr "レコードデータ"
msgid "Record Detail"
msgstr "レコードの詳細"
msgid "Record Type"
msgstr "レコード種別"
msgid "Records"
msgstr "レコード"
msgid "SOA"
msgstr "SOA"
msgid "SPF - Sender Policy Framework"
msgstr "SPF - Sender Policy Framework"
msgid "SRV - Service locator"
msgstr "SRV - サービスロケーター"
msgid "SSHFP - SSH Public Key Fingerprint"
msgstr "SSHFP - SSH 公開鍵フィンガープリント"
msgid "Select an IP"
msgstr "IP を選択してください"
msgid "Serial"
msgstr "シリアル"
msgid "TTL"
msgstr "TTL"
msgid "TTL (seconds)"
msgstr "TTL (秒)"
msgid "TXT"
msgstr "TXT"
msgid "TXT - Text record"
msgstr "TXT - テキストレコード"
msgid "Text"
msgstr "テキスト"
msgid "The quotas could not be retrieved."
msgstr "クォータを取得できませんでした。"
msgid "There are no floating IP addresses currently in use to select from."
msgstr "選択可能な現在使用中の Floating IP がありません。"
msgid "This field is required"
msgstr "このフィールドは必須です"
msgid "Type"
msgstr "種別"
msgid "Unable to create domain."
msgstr "ドメインを作成できません。"
msgid "Unable to create record."
msgstr "レコードを作成できません。"
msgid "Unable to retrieve domain list."
msgstr "ドメインの一覧を取得できません。"
msgid "Unable to retrieve domain record."
msgstr "ドメインレコードを取得できません。"
msgid "Unable to retrieve record list."
msgstr "レコードの一覧を取得できません。"
msgid "Unable to update domain."
msgstr "ドメインを更新できません。"
msgid "Unknown"
msgstr "不明"
msgid "Unknown instance name"
msgstr "不明なインスタンス名"
msgid "Update Domain"
msgstr "ドメインの更新"
msgid "Update Domain Record"
msgstr "ドメインレコードの更新"
msgid "Update Record"
msgstr "レコードの更新"
msgid "Updated"
msgstr "更新時刻"
msgid "Updated At"
msgstr "最終更新"
msgid "Value"
msgstr "値"
msgid "Zones"
msgstr "ゾーン"

Binary file not shown.

View File

@ -0,0 +1,350 @@
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# Ian Y. Choi <ianyrchoi@gmail.com>, 2016. #zanata
# Sungjin Kang <gang.sungjin@gmail.com>, 2016. #zanata
msgid ""
msgstr ""
"Project-Id-Version: designate-dashboard 3.0.0.0rc2.dev5\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2016-09-29 13:19+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2016-09-20 12:11+0000\n"
"Last-Translator: Ian Y. Choi <ianyrchoi@gmail.com>\n"
"Language-Team: Korean (South Korea)\n"
"Language: ko-KR\n"
"X-Generator: Zanata 3.7.3\n"
"Plural-Forms: nplurals=1; plural=0\n"
msgid ""
"\n"
" From here you can edit the email address and TTL associated with a "
"domain.\n"
" "
msgstr ""
"\n"
" 여기서부터 도메인과 연결된 이메일 주소와 TTL을 편집할 수 있습니다.\n"
" "
msgid ""
"\n"
" The Email field should contain a valid email address to be associated\n"
" with the domain.\n"
" "
msgstr ""
"\n"
" 이메일 피드는 도메인에 연결된 유료한 이메일 주소 값을\n"
" 포함해야 합니다.\n"
" "
msgid ""
"\n"
" The Name field should contain a full-qualified domain name (with\n"
" trailing period).\n"
" "
msgstr ""
"\n"
" 이름 필드는 정규화된 도메인 이름 (끝 마침표와 함께)을\n"
" 포함해야 합니다.\n"
" "
msgid ""
"\n"
" The optional TTL field can be any value between 1 and 2147483647\n"
" seconds.\n"
" "
msgstr ""
"\n"
" 옵션인 TTL 필드는 1 에서 2147483647 초 사이 임의의 값을\n"
" 사용할 수 있습니다.\n"
" "
msgid ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" The TTL is the time-to-live for the record, in seconds.\n"
" </p>\n"
" <p>\n"
" See <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">more info</a> on record types.\n"
" </p>\n"
" "
msgstr ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" TTL은 초 단위의 레코드에 대한 time-to-live 값입니다.\n"
" </p>\n"
" <p>\n"
" 레코드 유형에 관한 <a href=\"http://en.wikipedia.org/wiki/"
"List_of_DNS_record_types\" target=\"_designate_record_defs\">자세한 정보를</"
"a> 살펴봅니다.\n"
" </p>\n"
" "
msgid "A - Address record"
msgstr "A - 주소 레코드"
msgid "AAAA - IPv6 address record"
msgstr "AAAA - IPv6 주소 레코드"
msgid "All Records"
msgstr "모든 레코드"
msgid "CNAME - Canonical name record"
msgstr "CNAME - 대체 이름 레코드"
msgid "Cancel"
msgstr "취소"
msgid "Canonical Name"
msgstr "대체 이름"
msgid "Create Domain"
msgstr "도메인 생성"
msgid "Create Domain Record"
msgstr "도메인 레코드 생성"
msgid "Create Record"
msgstr "레코드 생성"
msgid "Create Record for"
msgstr "다음에 대한 레코드 생성"
msgid "Created"
msgstr "생성됨"
msgid "Created At"
msgstr "생성 시점"
msgid "Data"
msgstr "데이터"
msgid "Delete"
msgstr "삭제"
msgid "Deleted"
msgstr "삭제됨"
msgid "Description"
msgstr "설명"
msgid "Domain"
msgstr "도메인"
#, python-format
msgid "Domain %(name)s created."
msgstr "도메인 %(name)s 이 생성되었습니다."
#, python-format
msgid "Domain %(name)s updated."
msgstr "도메인 %(name)s 이 수정되었습니다."
msgid "Domain Detail"
msgstr "도메인 세부 사항"
msgid "Domain Name"
msgstr "도메인 이름"
msgid "Domain Overview"
msgstr "도메인 개요"
msgid "Domain Records"
msgstr "도메인 레코드"
#, python-format
msgid "Domain record %(name)s created."
msgstr "도메인 레코드 %(name)s 가 생성되었습니다."
#, python-format
msgid "Domain record %(name)s updated."
msgstr "도메인 레코드 %(name)s 가 업데이트되었습니다."
msgid "Domains"
msgstr "도메인"
msgid "Edit Domain"
msgstr "도메인 수정"
msgid "Edit Record"
msgstr "레코드 수정"
msgid "Email"
msgstr "이메일"
msgid "Enter a valid IPv4 address"
msgstr "유효한 IPv4 주소를 입력합니다"
msgid "Enter a valid IPv6 address"
msgstr "유요한 IPv6 주소를 입력합니다"
msgid "Enter a valid SRV name"
msgstr "유효한 SRV 이름을 입력합니다"
msgid "Enter a valid SRV record"
msgstr "유효한 SRV 레코드를 입력합니다"
msgid "Enter a valid SSHFP record"
msgstr "유효한 SSHFP 레코드를 입력합니다"
msgid "Enter a valid domain name."
msgstr "유효한 도메인 이름을 입력하시오."
msgid "Enter a valid hostname"
msgstr "유효한 호스트명을 입력합니다"
msgid ""
"Enter a valid hostname. The hostname should contain letters and numbers, and "
"be no more than 63 characters."
msgstr ""
"유효한 호스트명을 입력합니다. 호스트명은 문자 및 숫자로 구성되어야 하며, 63 "
"문자를 초과할 수 없습니다."
msgid "ID"
msgstr "ID"
msgid "IP Address"
msgstr "IP 주소"
msgid "MX - Mail exchange record"
msgstr "MX - 메일 교환 레코드"
msgid "Mail Server"
msgstr "메일 서버"
msgid "Manage Records"
msgstr "레코드 관리"
msgid "NS"
msgstr "NS"
msgid "Name"
msgstr "이름"
msgid "Name Server"
msgstr "네임 서버"
msgid "Nameservers"
msgstr "이름 서버"
msgid "None"
msgstr "없음"
msgid "PTR - Pointer record"
msgstr "PTR - 포인터 레코드"
msgid "PTR Domain Name"
msgstr "PTR 도메인 이름"
msgid "Priority"
msgstr "우선순위"
msgid "Record"
msgstr "레코드"
msgid "Record Data"
msgstr "레코드 데이터"
msgid "Record Detail"
msgstr "레코드 세부 사항"
msgid "Record Type"
msgstr "레코드 타입"
msgid "Records"
msgstr "레코드"
msgid "Reverse DNS"
msgstr "Reverse DNS"
msgid "SOA"
msgstr "SOA"
msgid "SPF - Sender Policy Framework"
msgstr "SPF - 발송자 정책 프레임워크"
msgid "SRV - Service locator"
msgstr "SRV - 서비스 위치"
msgid "SSHFP - SSH Public Key Fingerprint"
msgstr "SSHFP - SSH 공개키 Fingerprint"
msgid "Select an IP"
msgstr "IP를 선택합니다"
msgid "Serial"
msgstr "시리얼"
msgid "TTL"
msgstr "TTL"
msgid "TTL (seconds)"
msgstr "TTL (초)"
msgid "TXT"
msgstr "TXT"
msgid "TXT - Text record"
msgstr "TXT - 텍스트 레코드"
msgid "Text"
msgstr "텍스트"
msgid "The quotas could not be retrieved."
msgstr "할당량을 가져올 수 없습니다."
msgid "There are no floating IP addresses currently in use to select from."
msgstr "선택할 수 있는 사용 중인 floating IP 주소가 없습니다."
msgid "This field is required"
msgstr "해당 필드는 필수입니다"
msgid "Type"
msgstr "타입"
msgid "Unable to create domain."
msgstr "도메인을 생성할 수 없습니다."
msgid "Unable to create record."
msgstr "레코드를 생성할 수 없습니다."
msgid "Unable to retrieve domain list."
msgstr "도메인 목록을 가져올 수 없습니다."
msgid "Unable to retrieve domain record."
msgstr "도메인 레코드를 가져올 수 없습니다."
msgid "Unable to retrieve record list."
msgstr "레코드 목록을 가져올 수 없습니다."
msgid "Unable to update domain."
msgstr "도메인을 업데이트할 수 없습니다."
msgid "Unknown"
msgstr "알 수 없음"
msgid "Unknown instance name"
msgstr "알려지지 않은 인스턴스 이름"
msgid "Update Domain"
msgstr "도메인 업데이트"
msgid "Update Domain Record"
msgstr "도메인 레코드 업데이트"
msgid "Update Record"
msgstr "레코드 업데이트"
msgid "Updated"
msgstr "업데이트됨"
msgid "Updated At"
msgstr "갱신 시점"
msgid "Value"
msgstr "값"
msgid "Zones"
msgstr "존"

Binary file not shown.

View File

@ -0,0 +1,352 @@
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# Eric Baum <ecbaum@gmail.com>, 2016. #zanata
# Marcio <marciofoz@gmail.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: designate-dashboard 4.0.0.0rc2.dev10\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-03-10 19:52+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-03-15 07:16+0000\n"
"Last-Translator: Marcio <marciofoz@gmail.com>\n"
"Language-Team: Portuguese (Brazil)\n"
"Language: pt-BR\n"
"X-Generator: Zanata 3.9.6\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
msgid ""
"\n"
" From here you can edit the email address and TTL associated with a "
"domain.\n"
" "
msgstr ""
"\n"
" Aqui você pode editar o endereço de e-mail e o TTL associado ao "
"domínio.\n"
" "
msgid ""
"\n"
" The Email field should contain a valid email address to be associated\n"
" with the domain.\n"
" "
msgstr ""
"\n"
" O campo de Email deve conter um endereço de e-mail válido para ser\n"
" associado ao domínio.\n"
" "
msgid ""
"\n"
" The Name field should contain a full-qualified domain name (with\n"
" trailing period).\n"
" "
msgstr ""
"\n"
" O campo de nome deve conter um nome de domínio completamente "
"qualificado\n"
" ( com ponto final).\n"
" "
msgid ""
"\n"
" The optional TTL field can be any value between 1 and 2147483647\n"
" seconds.\n"
" "
msgstr ""
"\n"
" O campo opcional de TTL pode ter qualquer valor entre 1 e 2147483647\n"
" segundos.\n"
" "
msgid ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" The TTL is the time-to-live for the record, in seconds.\n"
" </p>\n"
" <p>\n"
" See <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">more info</a> on record types.\n"
" </p>\n"
" "
msgstr ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" O TTL é o tempo de vida do registro, em segundos.\n"
" </p>\n"
" <p>\n"
" Veja <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\"> para mais informações </a> nos tipos de "
"registro.\n"
" </p>\n"
" "
msgid "A - Address record"
msgstr "A - Registro do endereço"
msgid "AAAA - IPv6 address record"
msgstr "AAAA - Registro do endereço IPv6"
msgid "All Records"
msgstr "Todos os Registros"
msgid "CNAME - Canonical name record"
msgstr "CNAME - Registro Canonical name "
msgid "Cancel"
msgstr "Cancelar"
msgid "Canonical Name"
msgstr "Canonical Name"
msgid "Create Domain"
msgstr "Criar Domínio"
msgid "Create Domain Record"
msgstr "Criar Registro do Domínio"
msgid "Create Record"
msgstr "Criar Registro"
msgid "Create Record for"
msgstr "Criar Registro para"
msgid "Created"
msgstr "Criado"
msgid "Created At"
msgstr "Criado em"
msgid "Data"
msgstr "Dados"
msgid "Delete"
msgstr "Remover"
msgid "Deleted"
msgstr "Removido"
msgid "Description"
msgstr "Descrição"
msgid "Domain"
msgstr "Domínio"
#, python-format
msgid "Domain %(name)s created."
msgstr "Domínio %(name)s criado."
#, python-format
msgid "Domain %(name)s updated."
msgstr "Domínio %(name)s atualizado."
msgid "Domain Detail"
msgstr "Detalhes do Domínio"
msgid "Domain Name"
msgstr "Nome do Domínio"
msgid "Domain Overview"
msgstr "Visão Geral do Domínio"
msgid "Domain Records"
msgstr "Registros do Domínio"
#, python-format
msgid "Domain record %(name)s created."
msgstr "Registro de domínio %(name)s criado."
#, python-format
msgid "Domain record %(name)s updated."
msgstr "Registro de domínio %(name)s atualizado."
msgid "Domains"
msgstr "Domínios"
msgid "Edit Domain"
msgstr "Editar Domínio"
msgid "Edit Record"
msgstr "Editar Registro"
msgid "Email"
msgstr "Email"
msgid "Enter a valid IPv4 address"
msgstr "Entre com um endereço IPv4 válido"
msgid "Enter a valid IPv6 address"
msgstr "Entre com um endereço IPv6 válido"
msgid "Enter a valid SRV name"
msgstr "Entre com um nome SRV válido."
msgid "Enter a valid SRV record"
msgstr "Entre com um registro SRV válido"
msgid "Enter a valid SSHFP record"
msgstr "Entre com um registro SSHFP válido"
msgid "Enter a valid domain name."
msgstr "Entre com um nome de domínio válido."
msgid "Enter a valid hostname"
msgstr "Entre com um nome de host válido"
msgid ""
"Enter a valid hostname. The hostname should contain letters and numbers, and "
"be no more than 63 characters."
msgstr ""
"Insira um nome de host válido. O Nome de host deve conter letras e números, "
"e não pode ter mais de 63 caracteres."
msgid "ID"
msgstr "ID"
msgid "IP Address"
msgstr "Endereço IP"
msgid "MX - Mail exchange record"
msgstr "MX - Registro Mail exchange"
msgid "Mail Server"
msgstr "Servidor de Email"
msgid "Manage Records"
msgstr "Gerenciar Registros"
msgid "NS"
msgstr "NS"
msgid "Name"
msgstr "Nome"
msgid "Name Server"
msgstr "Servidor de Nome"
msgid "Nameservers"
msgstr "Servidores de Nome"
msgid "None"
msgstr "Nenhum"
msgid "PTR - Pointer record"
msgstr "PTR - Registro Pointer record"
msgid "PTR Domain Name"
msgstr "PTR Nome do Domínio"
msgid "Priority"
msgstr "Prioridade"
msgid "Record"
msgstr "Registro"
msgid "Record Data"
msgstr "Dados do Registro"
msgid "Record Detail"
msgstr "Detalhes do Registro"
msgid "Record Type"
msgstr "Tipo de Registro"
msgid "Records"
msgstr "Registros"
msgid "Reverse DNS"
msgstr "DNS Reverso"
msgid "SOA"
msgstr "SOA"
msgid "SPF - Sender Policy Framework"
msgstr "SPF - Sender Policy Framework"
msgid "SRV - Service locator"
msgstr "SRV - Service locator"
msgid "SSHFP - SSH Public Key Fingerprint"
msgstr "SSHFP - SSH Public Key Fingerprint"
msgid "Select an IP"
msgstr "Selecione um IP"
msgid "Serial"
msgstr "Serial"
msgid "TTL"
msgstr "TTL"
msgid "TTL (seconds)"
msgstr "TTL (segundos)"
msgid "TXT"
msgstr "TXT"
msgid "TXT - Text record"
msgstr "TXT - Text record"
msgid "Text"
msgstr "Text"
msgid "The quotas could not be retrieved."
msgstr "Não foi possível recuperar as cotas."
msgid "There are no floating IP addresses currently in use to select from."
msgstr "Nenhum endereço IP flutuante atualmente em uso para ser selecionado."
msgid "This field is required"
msgstr "Este campo é necessário"
msgid "Type"
msgstr "Tipo"
msgid "Unable to create domain."
msgstr "Não foi possível criar o domínio."
msgid "Unable to create record."
msgstr "Não é possível criar o registro."
msgid "Unable to retrieve domain list."
msgstr "Não foi possível recuperar a lista de domínios."
msgid "Unable to retrieve domain record."
msgstr "Não foi possível recuperar o registro de domínio."
msgid "Unable to retrieve record list."
msgstr "Não é possível recuperar lista de registros."
msgid "Unable to update domain."
msgstr "Não foi possível atualizar o domínio."
msgid "Unknown"
msgstr "Desconhecido"
msgid "Unknown instance name"
msgstr "Nome de Instância desconhecida"
msgid "Update Domain"
msgstr "Atualizar Domínio"
msgid "Update Domain Record"
msgstr "Atualizar Registro do Domínio"
msgid "Update Record"
msgstr "Atualizar Registro"
msgid "Updated"
msgstr "Atualizado"
msgid "Updated At"
msgstr "Atualizado em"
msgid "Value"
msgstr "Valor"
msgid "Zones"
msgstr "Zonas"

Binary file not shown.

View File

@ -0,0 +1,361 @@
# Translations template for designate-dashboard.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the designate-dashboard
# project.
#
# Translators:
# Denis Gubanov <v12aml@gmail.com>, 2015
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# Ivan Startsev <istartsev67@gmail.com>, 2016. #zanata
# Ilya Alekseyev <ilyaalekseyev@acm.org>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: designate-dashboard 4.0.0.0rc2.dev10\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-03-10 19:52+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-03-23 08:04+0000\n"
"Last-Translator: Ilya Alekseyev <ilyaalekseyev@acm.org>\n"
"Language: ru\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
"%100>=11 && n%100<=14)? 2 : 3);\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.9.6\n"
"Language-Team: Russian\n"
msgid ""
"\n"
" From here you can edit the email address and TTL associated with a "
"domain.\n"
" "
msgstr ""
"\n"
" Отсюда вы можете отредактировать адрес почты и ассоциированный с "
"доменом TTL \n"
" "
msgid ""
"\n"
" The Email field should contain a valid email address to be associated\n"
" with the domain.\n"
" "
msgstr ""
"\n"
" Поле Почта должно содержать валидный почтовый адрес\n"
" который может быть ассоциирован с доменом.\n"
" "
msgid ""
"\n"
" The Name field should contain a full-qualified domain name (with\n"
" trailing period).\n"
" "
msgstr ""
"\n"
" Поле Имя должно содержать полностью определённое имя домена (FQDN) "
"( с\n"
" завершающей точкой).\n"
" "
msgid ""
"\n"
" The optional TTL field can be any value between 1 and 2147483647\n"
" seconds.\n"
" "
msgstr ""
"\n"
" Опциональное поле TTL может принимать любое значение \n"
" между 1 и 2147483647 секундами.\n"
" "
msgid ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" The TTL is the time-to-live for the record, in seconds.\n"
" </p>\n"
" <p>\n"
" See <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">more info</a> on record types.\n"
" </p>\n"
" "
msgstr ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" TTL - это time-to-live для записи, в секундах.\n"
" </p>\n"
" <p>\n"
" See <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">больше информации</a> на типах записи.\n"
" </p>\n"
" "
msgid "A - Address record"
msgstr "A - IPv4 адрес"
msgid "AAAA - IPv6 address record"
msgstr "AAAA - IPv6 адрес"
msgid "All Records"
msgstr "Все Записи"
msgid "CNAME - Canonical name record"
msgstr "CNAME - каноническое имя"
msgid "Cancel"
msgstr "Отмена"
msgid "Canonical Name"
msgstr "Каноническое имя"
msgid "Create Domain"
msgstr "Создать домен"
msgid "Create Domain Record"
msgstr "Создать Доменную Запись"
msgid "Create Record"
msgstr "Создать запись"
msgid "Create Record for"
msgstr "Создать запись для"
msgid "Created"
msgstr "Создано"
msgid "Created At"
msgstr "Создано"
msgid "Data"
msgstr "Данные"
msgid "Delete"
msgstr "Удалить"
msgid "Deleted"
msgstr "Удалено"
msgid "Description"
msgstr "Описание"
msgid "Domain"
msgstr "Домен"
#, python-format
msgid "Domain %(name)s created."
msgstr "Домен %(name)s создан."
#, python-format
msgid "Domain %(name)s updated."
msgstr "Домен %(name)s обновлен."
msgid "Domain Detail"
msgstr "Детали Домена"
msgid "Domain Name"
msgstr "Имя домена"
msgid "Domain Overview"
msgstr "Обзор Домена"
msgid "Domain Records"
msgstr "Записи Домена"
#, python-format
msgid "Domain record %(name)s created."
msgstr "Доменная запись %(name)s создана."
#, python-format
msgid "Domain record %(name)s updated."
msgstr "Доменная запись %(name)s обновлена."
msgid "Domains"
msgstr "Домены"
msgid "Edit Domain"
msgstr "Редактировать домен"
msgid "Edit Record"
msgstr "Редактировать запись"
msgid "Email"
msgstr "Email"
msgid "Enter a valid IPv4 address"
msgstr "Введите корректный IPv4 адрес"
msgid "Enter a valid IPv6 address"
msgstr "Введите корректный IPv6 адрес"
msgid "Enter a valid SRV name"
msgstr "Введите верное SRV имя"
msgid "Enter a valid SRV record"
msgstr "Введите корректную SRV запись"
msgid "Enter a valid SSHFP record"
msgstr "Введите корректныю SSHFP запись"
msgid "Enter a valid domain name."
msgstr "Введите корректное имя домена"
msgid "Enter a valid hostname"
msgstr "Введите корректное имя узла"
msgid ""
"Enter a valid hostname. The hostname should contain letters and numbers, and "
"be no more than 63 characters."
msgstr ""
"Введите верное имя узла. Имя узла должно содержать буквы, цифры и быть не "
"длиннее 63 символов."
msgid "ID"
msgstr "ID"
msgid "IP Address"
msgstr "IP адрес"
msgid "MX - Mail exchange record"
msgstr "MX - почтовый узел"
msgid "Mail Server"
msgstr "Почтовый сервер"
msgid "Manage Records"
msgstr "Управление записями"
msgid "NS"
msgstr "NS"
msgid "Name"
msgstr "Имя"
msgid "Name Server"
msgstr "Сервер имен"
msgid "Nameservers"
msgstr "сервера"
msgid "None"
msgstr "Нет"
msgid "PTR - Pointer record"
msgstr "PTR - указатель на каноническое имя"
msgid "PTR Domain Name"
msgstr "Имя домена PTR"
msgid "Priority"
msgstr "Приоритет"
msgid "Record"
msgstr "Запись"
msgid "Record Data"
msgstr "Запись Данных"
msgid "Record Detail"
msgstr "Детали Записи"
msgid "Record Type"
msgstr "Тип записи"
msgid "Records"
msgstr "Записи"
msgid "Reverse DNS"
msgstr "Обратный DNS"
msgid "SOA"
msgstr "SOA"
msgid "SPF - Sender Policy Framework"
msgstr "SPF - инфраструктура политики отправителя"
msgid "SRV - Service locator"
msgstr "SRV - указатель сервиса"
msgid "SSHFP - SSH Public Key Fingerprint"
msgstr "SSHFP - отпечаток публичного ключа SSH"
msgid "Select an IP"
msgstr "Выберите IP"
msgid "Serial"
msgstr "Серийный номер"
msgid "TTL"
msgstr "TTL"
msgid "TTL (seconds)"
msgstr "TTL (секунды)"
msgid "TXT"
msgstr "TXT"
msgid "TXT - Text record"
msgstr "TXT - тестовая запись"
msgid "Text"
msgstr "Текст"
msgid "The quotas could not be retrieved."
msgstr "Невозможно получить квоты."
msgid "There are no floating IP addresses currently in use to select from."
msgstr "Отсутствуют используемые плавающие IP-адреса для выбора."
msgid "This field is required"
msgstr "Это поле обязательно"
msgid "Type"
msgstr "Тип"
msgid "Unable to create domain."
msgstr "Невозможно создать домен."
msgid "Unable to create record."
msgstr "Невозможно создать запись."
msgid "Unable to retrieve domain list."
msgstr "Невозможно получить список доменов."
msgid "Unable to retrieve domain record."
msgstr "Невозможно получить список записей."
msgid "Unable to retrieve record list."
msgstr "Невозможно получить список записей."
msgid "Unable to update domain."
msgstr "Невозможно обновить домен."
msgid "Unknown"
msgstr "Неизвестно"
msgid "Unknown instance name"
msgstr "Неизвестное имя инстанса"
msgid "Update Domain"
msgstr "Обновить Домен"
msgid "Update Domain Record"
msgstr "Обновить Доменную Запись"
msgid "Update Record"
msgstr "Обновить запись"
msgid "Updated"
msgstr "Обновлено"
msgid "Updated At"
msgstr "Обновлено"
msgid "Value"
msgstr "Значение"
msgid "Zones"
msgstr "Зоны"

Binary file not shown.

View File

@ -0,0 +1,360 @@
# Translations template for designate-dashboard.
# Copyright (C) 2015 ORGANIZATION
# This file is distributed under the same license as the designate-dashboard
# project.
#
# Translators:
# Alper Çiftçi <alprciftci@gmail.com>, 2015
# Mücahit Büyükyılmaz <mucahit@deltanoc.com>, 2015. #zanata
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# işbaran akçayır <isbaran@gmail.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: designate-dashboard 5.0.0.0b2.dev8\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-05-18 22:12+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-05-22 08:57+0000\n"
"Last-Translator: Copied by Zanata <copied-by-zanata@zanata.org>\n"
"Language: tr-TR\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.9.6\n"
"Language-Team: Turkish (Turkey)\n"
msgid ""
"\n"
" From here you can edit the email address and TTL associated with a "
"domain.\n"
" "
msgstr ""
"\n"
" Burdan alan ile ilişkili eposta adresini ve TTL değerini "
"düzenleyebilirsiniz.\n"
" "
msgid ""
"\n"
" The Email field should contain a valid email address to be associated\n"
" with the domain.\n"
" "
msgstr ""
"\n"
" Eposta alanı alan ile ilişkilendirilecek geçerli bir\n"
" eposta adresi içermelidir.\n"
" "
msgid ""
"\n"
" The Name field should contain a full-qualified domain name (with\n"
" trailing period).\n"
" "
msgstr ""
"\n"
" İsim alanı tam-nitelikli alan adı içermelidir\n"
" (sonunda nokta ile).\n"
" "
msgid ""
"\n"
" The optional TTL field can be any value between 1 and 2147483647\n"
" seconds.\n"
" "
msgstr ""
"\n"
" İsteğe bağlı TTL alanı 1 ve 2147483647 saniye arasında\n"
" bir sayı olabilir.\n"
" "
msgid ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" The TTL is the time-to-live for the record, in seconds.\n"
" </p>\n"
" <p>\n"
" See <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">more info</a> on record types.\n"
" </p>\n"
" "
msgstr ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" TTL kaydın yaşam süresidir, saniye olarak.\n"
" </p>\n"
" <p>\n"
" Kayıt türleri hakkında <a href=\"http://en.wikipedia.org/wiki/"
"List_of_DNS_record_types\" target=\"_designate_record_defs\">daha fazla "
"bilgi için</a> bakınız.\n"
" </p>\n"
" "
msgid "A - Address record"
msgstr "A - Adres kaydı"
msgid "AAAA - IPv6 address record"
msgstr "AAAA - IPv6 adres kaydı"
msgid "All Records"
msgstr "Tüm Kayıtlar"
msgid "CNAME - Canonical name record"
msgstr "CNAME - Meşru isim kaydı"
msgid "Cancel"
msgstr "İptal"
msgid "Canonical Name"
msgstr "Meşru isim"
msgid "Create Domain"
msgstr "Alan Oluştur"
msgid "Create Domain Record"
msgstr "Alan Kaydı Oluştur"
msgid "Create Record"
msgstr "Kayıt Oluştur"
msgid "Create Record for"
msgstr "Kayıt oluştur"
msgid "Created"
msgstr "Oluşturuldu"
msgid "Created At"
msgstr "Oluşturulduğu zaman"
msgid "Data"
msgstr "Veri"
msgid "Delete"
msgstr "Sil"
msgid "Deleted"
msgstr "Silindi"
msgid "Description"
msgstr "Açıklama"
msgid "Domain"
msgstr "Alan"
#, python-format
msgid "Domain %(name)s created."
msgstr "%(name)s alanı oluşturuldu"
#, python-format
msgid "Domain %(name)s updated."
msgstr "%(name)s alanı güncellendi"
msgid "Domain Detail"
msgstr "Alan Ayrıntısı"
msgid "Domain Name"
msgstr "Alan Adı"
msgid "Domain Overview"
msgstr "Alan Genel Görünümü"
msgid "Domain Records"
msgstr "Alan Kayıtları"
#, python-format
msgid "Domain record %(name)s created."
msgstr "%(name)s alan kaydı oluşturuldu"
#, python-format
msgid "Domain record %(name)s updated."
msgstr "%(name)s alan kaydı güncellendi"
msgid "Domains"
msgstr "Alanlar"
msgid "Edit Domain"
msgstr "Alan Değiştir"
msgid "Edit Record"
msgstr "Kaydı Düzenle"
msgid "Email"
msgstr "E-posta"
msgid "Enter a valid IPv4 address"
msgstr "Geçerli bir IPv4 adresi girin"
msgid "Enter a valid IPv6 address"
msgstr "Geçerli bir IPv6 adresi girin"
msgid "Enter a valid SRV name"
msgstr "Geçerli bir SRV adı girin"
msgid "Enter a valid SRV record"
msgstr "Geçerli bir SRV kaydı girin"
msgid "Enter a valid SSHFP record"
msgstr "Geçerli bir SSHFP kaydı girin"
msgid "Enter a valid domain name."
msgstr "Geçerli bir alan adı girin"
msgid "Enter a valid hostname"
msgstr "Geçerli bir sunucu adı girin"
msgid ""
"Enter a valid hostname. The hostname should contain letters and numbers, and "
"be no more than 63 characters."
msgstr ""
"Geçerli bir sunucu adı girin. Sunucu adı 63 karakterden az olmayan harf ve "
"sayılar içermektedir."
msgid "ID"
msgstr "KİMLİK"
msgid "IP Address"
msgstr "IP Adresi"
msgid "MX - Mail exchange record"
msgstr "MX - Posta değişim kaydı"
msgid "Mail Server"
msgstr "Posta Sunucusu"
msgid "Manage Records"
msgstr "Kayıtları Yönet"
msgid "NS"
msgstr "NS"
msgid "Name"
msgstr "İsim"
msgid "Name Server"
msgstr "İsim Sunucusu"
msgid "Nameservers"
msgstr "İsim sunucular"
msgid "None"
msgstr "Yok"
msgid "PTR - Pointer record"
msgstr "PTR - İşaretçi kaydı"
msgid "PTR Domain Name"
msgstr "PTR Alan Adı"
msgid "Priority"
msgstr "Öncelik"
msgid "Record"
msgstr "Kayıt"
msgid "Record Data"
msgstr "Kayıt Verisi"
msgid "Record Detail"
msgstr "Kayıt Ayrıntısı"
msgid "Record Type"
msgstr "Kayıt Tipi"
msgid "Records"
msgstr "Kayıtlar"
msgid "Reverse DNS"
msgstr "Ters DNS"
msgid "SOA"
msgstr "SOA"
msgid "SPF - Sender Policy Framework"
msgstr "SPF - Gönderen İlkesi Çatısı"
msgid "SRV - Service locator"
msgstr "SRV - Servis konumlandırıcı"
msgid "SSHFP - SSH Public Key Fingerprint"
msgstr "SSHFP - SSH Açık Anahtar Parmakizi"
msgid "Select an IP"
msgstr "Bir IP seçiniz"
msgid "Serial"
msgstr "Seri"
msgid "TTL"
msgstr "TTL"
msgid "TTL (seconds)"
msgstr "TTL (saniye)"
msgid "TXT"
msgstr "TXT"
msgid "TXT - Text record"
msgstr "TXT - Yazı Kaydı"
msgid "Text"
msgstr "Yazı"
msgid "The quotas could not be retrieved."
msgstr "Kotalar alınamadı."
msgid "There are no floating IP addresses currently in use to select from."
msgstr "Seçilecek kullanılabilir değişken IP adresi yok."
msgid "This field is required"
msgstr "Bu alanın doldurulması gerekmektedir."
msgid "Type"
msgstr "Tip"
msgid "Unable to create domain."
msgstr "Alan yaratılamıyor"
msgid "Unable to create record."
msgstr "Kayıt oluşturulamıyor"
msgid "Unable to retrieve domain list."
msgstr "Alan listesi alınamıyor."
msgid "Unable to retrieve domain record."
msgstr "Alan kaydı alınamadı."
msgid "Unable to retrieve record list."
msgstr "Kayıt listesi alınamadı."
msgid "Unable to update domain."
msgstr "Alan güncellenemiyor."
msgid "Unknown"
msgstr "Bilinmeyen"
msgid "Unknown instance name"
msgstr "Bilinmeyen mesafe adı"
msgid "Update Domain"
msgstr "Alanı Güncelle"
msgid "Update Domain Record"
msgstr "Alan Kaydını Güncelle"
msgid "Update Record"
msgstr "Kaydı Güncelle"
msgid "Updated"
msgstr "Güncellendi"
msgid "Updated At"
msgstr "Güncellendiği Zaman"
msgid "Value"
msgstr "Değer"
msgid "Zones"
msgstr "Bölgeler"

Binary file not shown.

View File

@ -0,0 +1,353 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
# Gaoxiao Zhu <zhu.gaoxiao@h3c.com>, 2016. #zanata
# Linda <duleish@cn.ibm.com>, 2016. #zanata
# Wu Han <wu.han@h3c.com>, 2016. #zanata
# ZHIYUAN SU <suzhiyuan@inspur.com>, 2016. #zanata
# vuuv <froms2008@gmail.com>, 2016. #zanata
# zzxwill <zzxwill@gmail.com>, 2016. #zanata
# vuuv <froms2008@gmail.com>, 2017. #zanata
msgid ""
msgstr ""
"Project-Id-Version: designate-dashboard 4.0.0.0rc2.dev10\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
"POT-Creation-Date: 2017-03-10 19:52+0000\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-03-23 08:04+0000\n"
"Last-Translator: vuuv <froms2008@gmail.com>\n"
"Language-Team: Chinese (China)\n"
"Language: zh-CN\n"
"X-Generator: Zanata 3.9.6\n"
"Plural-Forms: nplurals=1; plural=0\n"
msgid ""
"\n"
" From here you can edit the email address and TTL associated with a "
"domain.\n"
" "
msgstr ""
"\n"
"从这里可以编辑邮件地址和关联到一个域的TTL\n"
" "
msgid ""
"\n"
" The Email field should contain a valid email address to be associated\n"
" with the domain.\n"
" "
msgstr ""
"\n"
"电子邮件项应包括一个有效的邮件地址来\n"
"跟域名进行关联。\n"
" "
msgid ""
"\n"
" The Name field should contain a full-qualified domain name (with\n"
" trailing period).\n"
" "
msgstr ""
"\n"
"名称项应该包含一个完全合格的域名(有一个\n"
"尾随句点)。\n"
" "
msgid ""
"\n"
" The optional TTL field can be any value between 1 and 2147483647\n"
" seconds.\n"
" "
msgstr ""
"\n"
"可选的TTL项可以是1到2147483647之间的任何\n"
"秒数。\n"
" "
msgid ""
"\n"
" <p>\n"
" <strong>TTL</strong>\n"
" The TTL is the time-to-live for the record, in seconds.\n"
" </p>\n"
" <p>\n"
" See <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types\" "
"target=\"_designate_record_defs\">more info</a> on record types.\n"
" </p>\n"
" "
msgstr ""
"\n"
"<p>\n"
"<strong>TTL</strong>\n"
"TTL是指 记录的存活时间或者存在时间,单位为秒。\n"
"</p>\n"
"<p>\n"
"见记录类型的 <a href=\"http://en.wikipedia.org/wiki/List_of_DNS_record_types"
"\" target=\"_designate_record_defs\">更多信息</a>。\n"
"</p>\n"
" "
msgid "A - Address record"
msgstr "A-地址记录"
msgid "AAAA - IPv6 address record"
msgstr "AAAA-IPv6地址记录"
msgid "All Records"
msgstr "所有记录"
msgid "CNAME - Canonical name record"
msgstr "CNAME-标准名称记录"
msgid "Cancel"
msgstr "取消"
msgid "Canonical Name"
msgstr "规范名称"
msgid "Create Domain"
msgstr "创建域"
msgid "Create Domain Record"
msgstr "创建域记录"
msgid "Create Record"
msgstr "创建记录"
msgid "Create Record for"
msgstr "创建记录为:"
msgid "Created"
msgstr "已创建"
msgid "Created At"
msgstr "创建于"
msgid "Data"
msgstr "数据"
msgid "Delete"
msgstr "删除"
msgid "Deleted"
msgstr "已删除"
msgid "Description"
msgstr "描述"
msgid "Domain"
msgstr "域"
#, python-format
msgid "Domain %(name)s created."
msgstr "域 %(name)s 已创建"
#, python-format
msgid "Domain %(name)s updated."
msgstr "域%(name)s已更新"
msgid "Domain Detail"
msgstr "域明细"
msgid "Domain Name"
msgstr "域名"
msgid "Domain Overview"
msgstr "域概览"
msgid "Domain Records"
msgstr "域记录"
#, python-format
msgid "Domain record %(name)s created."
msgstr "创建的域记录数 %(name)s "
#, python-format
msgid "Domain record %(name)s updated."
msgstr "更新的域记录数 %(name)s"
msgid "Domains"
msgstr "域"
msgid "Edit Domain"
msgstr "编辑域"
msgid "Edit Record"
msgstr "编辑记录"
msgid "Email"
msgstr "邮箱"
msgid "Enter a valid IPv4 address"
msgstr "输入一个有效的IPv4地址"
msgid "Enter a valid IPv6 address"
msgstr "输入一个有效的IPv6地址"
msgid "Enter a valid SRV name"
msgstr "输入一个有效的SRV名"
msgid "Enter a valid SRV record"
msgstr "输入一个有效的SRV记录"
msgid "Enter a valid SSHFP record"
msgstr "输入一个有效的SSHFP记录"
msgid "Enter a valid domain name."
msgstr "输入一个有效域名"
msgid "Enter a valid hostname"
msgstr "输入一个有效的主机名"
msgid ""
"Enter a valid hostname. The hostname should contain letters and numbers, and "
"be no more than 63 characters."
msgstr "输入一个有效的主机名。该主机名应包含字母和数字且不多余63个字符。"
msgid "ID"
msgstr "标识"
msgid "IP Address"
msgstr "IP 地址"
msgid "MX - Mail exchange record"
msgstr "MX-邮件交换记录"
msgid "Mail Server"
msgstr "邮件服务器"
msgid "Manage Records"
msgstr "管理记录"
msgid "NS"
msgstr "NS"
msgid "Name"
msgstr "名称"
msgid "Name Server"
msgstr "域名服务器"
msgid "Nameservers"
msgstr "名称服务器数"
msgid "None"
msgstr "无"
msgid "PTR - Pointer record"
msgstr "PTR-指针记录"
msgid "PTR Domain Name"
msgstr "域名"
msgid "Priority"
msgstr "优先级"
msgid "Record"
msgstr "记录"
msgid "Record Data"
msgstr "记录数据"
msgid "Record Detail"
msgstr "记录明细"
msgid "Record Type"
msgstr "记录类型"
msgid "Records"
msgstr "记录数"
msgid "Reverse DNS"
msgstr "反向解析域名"
msgid "SOA"
msgstr "SOA"
msgid "SPF - Sender Policy Framework"
msgstr "SPF-发送方策略框架"
msgid "SRV - Service locator"
msgstr "SRV-服务定位器"
msgid "SSHFP - SSH Public Key Fingerprint"
msgstr "SSHFP-SSH公钥指纹"
msgid "Select an IP"
msgstr "选择一个IP"
msgid "Serial"
msgstr "序列号"
msgid "TTL"
msgstr "TTL"
msgid "TTL (seconds)"
msgstr "生存时间(秒)"
msgid "TXT"
msgstr "TXT"
msgid "TXT - Text record"
msgstr "TXT-文本记录"
msgid "Text"
msgstr "文本"
msgid "The quotas could not be retrieved."
msgstr "无法获取配额"
msgid "There are no floating IP addresses currently in use to select from."
msgstr "没有可以从中选择的使用中的浮动IP地址"
msgid "This field is required"
msgstr "需要此字段"
msgid "Type"
msgstr "类型"
msgid "Unable to create domain."
msgstr "无法创建域"
msgid "Unable to create record."
msgstr "不能创建记录。"
msgid "Unable to retrieve domain list."
msgstr "无法获取域列表。"
msgid "Unable to retrieve domain record."
msgstr "无法获取域记录"
msgid "Unable to retrieve record list."
msgstr "无法获取记录列表"
msgid "Unable to update domain."
msgstr "无法更新域"
msgid "Unknown"
msgstr "未知"
msgid "Unknown instance name"
msgstr "未知实例名"
msgid "Update Domain"
msgstr "更新域"
msgid "Update Domain Record"
msgstr "更新域记录"
msgid "Update Record"
msgstr "更新记录"
msgid "Updated"
msgstr "已更新"
msgid "Updated At"
msgstr "已更新于"
msgid "Value"
msgstr "值"
msgid "Zones"
msgstr "区域"

View File

@ -0,0 +1,78 @@
/**
* (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
/**
* @ngdoc overview
* @ngname designatedashboard
*
* @description
* Provides the services and widgets required
* to support and display the project search panel.
*/
angular
.module('designatedashboard', [
'ngRoute',
'designatedashboard.resources'
])
.constant(
'designatedashboard.apiPassthroughUrl', '/api/dns/')
.config(config)
.run(run);
config.$inject = [
'$provide',
'$routeProvider',
'$windowProvider'
];
/**
* @name designatedashboard.basePath
* @description Base path for the project dashboard
*
* @param {function} $provide ng provide service
*
* @param {function} $routeProvider ng route service
*
* @param {function} $windowProvider NG window provider
*
* @returns {undefined}
*/
function config($provide, $routeProvider, $windowProvider) {
var path = $windowProvider.$get().STATIC_URL + 'designatedashboard/';
$provide.constant('designatedashboard.basePath', path);
$routeProvider
.when('/project/dnszones/', {
templateUrl: path + 'zones.html'
})
.when('/project/reverse_dns/', {
templateUrl: path + 'reverse_dns.html'
});
}
run.$inject = [
'horizon.framework.conf.resource-type-registry.service',
'designatedashboard.basePath'
];
function run(registry, basePath) {
//registry.setDefaultSummaryTemplateUrl(basePath + 'table/default-drawer.html');
}
})();

View File

@ -0,0 +1,66 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
/**
* @ngdoc overview
* @ngname designatedashboard.resources.os-designate-floatingip.actions
*
* @description
* Provides all of the actions for DNS Floating IPs.
*/
angular.module('designatedashboard.resources.os-designate-floatingip.actions', [
'horizon.framework.conf',
'horizon.app.core'
])
.run(run);
run.$inject = [
'horizon.framework.conf.resource-type-registry.service',
'designatedashboard.resources.os-designate-floatingip.resourceType',
'designatedashboard.resources.os-designate-floatingip.actions.set',
'designatedashboard.resources.os-designate-floatingip.actions.unset'
];
function run(
registry,
resourceTypeString,
setAction,
unsetAction)
{
var resourceType = registry.getResourceType(resourceTypeString);
resourceType
.itemActions
.append({
id: 'setFloatingIp',
service: setAction,
template: {
text: gettext('Set')
}
})
.append({
id: 'unsetFloatingIp',
service: unsetAction,
template: {
text: gettext('Unset')
}
});
}
})();

View File

@ -0,0 +1,170 @@
/**
*
* (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use self file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function () {
'use strict';
angular
.module('designatedashboard.resources.os-designate-floatingip.actions')
.factory('designatedashboard.resources.os-designate-floatingip.actions.set', action);
action.$inject = [
'$q',
'designatedashboard.resources.os-designate-floatingip.api',
'designatedashboard.resources.os-designate-floatingip.resourceType',
'designatedashboard.resources.util',
'horizon.app.core.openstack-service-api.serviceCatalog',
'horizon.framework.widgets.form.ModalFormService',
'horizon.framework.widgets.toast.service',
'horizon.framework.widgets.modal-wait-spinner.service'
];
/**
* @ngDoc factory
* @name designatedashboard.resources.os-designate-floatingip.actions.set
*
* @Description
* Brings up the Set Floating IP modal.
*/
function action($q,
api,
resourceTypeName,
util,
serviceCatalog,
schemaFormModalService,
toast,
waitSpinner) {
var dnsServiceEnabled;
var title = null; // Set once perform is called
var formConfig = {
"schema": {
"type": "object",
"properties": {
"ptrdname": {
"type": "string",
"pattern": /^.+\.$/
},
"description": {
"type": "string"
},
"ttl": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
}
},
"form": [
{
"key": "ptrdname",
"title": gettext("Domain Name"),
"description": gettext("Domain name ending in '.'"),
"validationMessage": gettext("Domain must end with '.'"),
"placeholder": "smtp.example.com.",
"type": "text",
"required": true
},
{
"key": "description",
"type": "textarea",
"title": gettext("Description"),
"description": gettext("Details about the PTR record.")
},
{
"key": "ttl",
"title": gettext("TTL"),
"description": gettext("Time To Live in seconds."),
"type": "number"
}
]
};
var message = {
success: gettext('Domain name PTR %s was successfully set.')
};
var service = {
initScope: initScope,
allowed: allowed,
perform: perform
};
return service;
/////////////////
function initScope() {
dnsServiceEnabled = serviceCatalog.ifTypeEnabled('dns');
}
function allowed(item) {
return $q.all([
// TODO (tyr) designate currently has no floating ips policy rules
dnsServiceEnabled,
util.notPending(item)
]);
}
function perform(item) {
// Initialize the per-item title for use now and during submit
title = gettext("Set Domain Name PTR for ") + item.address;
formConfig.title = title;
// Get a form model based on the current item
formConfig.model = util.getModel(formConfig.form, item);
// Initialize default data
formConfig.model.ttl = formConfig.model.ttl || 3600;
// Remember the ID for use during submit
formConfig.model.floatingIpId = item.id;
return schemaFormModalService.open(formConfig).then(onSubmit, onCancel);
}
function onSubmit(context) {
var model = angular.copy(context.model);
var floatingIpId = formConfig.model.floatingIpId;
waitSpinner.showModalSpinner(title);
return api.set(floatingIpId, model).then(onSuccess, onFailure);
}
function onCancel() {
waitSpinner.hideModalSpinner();
}
function onSuccess(response) {
waitSpinner.hideModalSpinner();
var floatingIp = response.data;
toast.add('success', interpolate(message.success, [floatingIp.ptrdname]));
// To make the result of this action generically useful, reformat the return
// from the deleteModal into a standard form
return {
created: [],
updated: [{type: resourceTypeName, id: floatingIp.id}],
deleted: [],
failed: []
};
}
function onFailure() {
waitSpinner.hideModalSpinner();
}
}
})();

View File

@ -0,0 +1,139 @@
/**
*
* (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use self file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function () {
'use strict';
angular
.module('designatedashboard.resources.os-designate-floatingip.actions')
.factory('designatedashboard.resources.os-designate-floatingip.actions.unset', action);
action.$inject = [
'$q',
'designatedashboard.resources.os-designate-floatingip.api',
'designatedashboard.resources.os-designate-floatingip.resourceType',
'designatedashboard.resources.util',
'horizon.app.core.openstack-service-api.serviceCatalog',
'horizon.framework.util.q.extensions',
'horizon.framework.widgets.form.ModalFormService',
'horizon.framework.widgets.toast.service',
'horizon.framework.widgets.modal-wait-spinner.service'
];
/**
* @ngDoc factory
* @name designatedashboard.resources.os-designate-floatingip.actions.unset
*
* @Description
* Brings up the Unset Floating IP modal.
*/
function action($q,
api,
resourceTypeName,
util,
serviceCatalog,
$qExtensions,
schemaFormModalService,
toast,
waitSpinner) {
var dnsServiceEnabled;
var title = null; // Set on perform
var currentFloatingIpId; // Used to remember the ID we are modifying since it isn't returned by the unset API call
// Unset it just a simple case of "set", but with ptrdname of 'null'
var formConfig = {
"schema": {
"type": "object",
"properties": {
}
},
"form": [
],
"model": {
}
};
var message = {
success: gettext('Domain name PTR successfully unset.')
};
var service = {
initScope: initScope,
allowed: allowed,
perform: perform
};
return service;
/////////////////
function initScope() {
dnsServiceEnabled = serviceCatalog.ifTypeEnabled('dns');
}
function allowed(item) {
return $q.all([
// TODO (tyr) designate currently has no floating ip policy rules
dnsServiceEnabled,
domainNameSet(item),
util.notPending(item)
]);
}
function domainNameSet(item) {
return $qExtensions.booleanAsPromise(
angular.isString(item.ptrdname)
);
}
function perform(item) {
title = gettext("Unset Domain Name PTR for ") + item.address;
// Store the zone ID so it can be used on submit
formConfig.model.floatingIpId = item.id;
formConfig.title = title;
return schemaFormModalService.open(formConfig).then(onSubmit, onCancel);
}
function onSubmit(context) {
waitSpinner.showModalSpinner(title);
currentFloatingIpId = context.model.floatingIpId;
return api.unset(currentFloatingIpId).then(onSuccess, onFailure);
}
function onCancel() {
waitSpinner.hideModalSpinner();
}
function onSuccess(response) {
waitSpinner.hideModalSpinner();
toast.add('success', message.success);
// To make the result of this action generically useful, reformat the return
// from the deleteModal into a standard form
return {
created: [],
updated: [{type: resourceTypeName, id: currentFloatingIpId}],
deleted: [],
failed: []
};
}
function onFailure() {
waitSpinner.hideModalSpinner();
}
}
})();

View File

@ -0,0 +1,121 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function () {
'use strict';
angular
.module('designatedashboard.resources.os-designate-floatingip')
.factory('designatedashboard.resources.os-designate-floatingip.api', apiService);
apiService.$inject = [
'designatedashboard.apiPassthroughUrl',
'horizon.framework.util.http.service',
'horizon.framework.widgets.toast.service'
];
/**
* @ngdoc service
* @param {Object} httpService
* @param {Object} toastService
* @name apiService
* @description Provides direct access to Designate Floating IP APIs.
* @returns {Object} The service
*/
function apiService(apiPassthroughUrl, httpService, toastService) {
var service = {
list: list,
get: get,
set: set,
unset: unset
};
return service;
///////////////
/**
* @name list
* @description
* Get a list of DNS floating ips.
*
* The listing result is an object with property "items." Each item is
* a floating IP PTR record.
*
* @param {Object} params
* Query parameters. Optional.
*
* @returns {Object} The result of the API call
*/
function list(params) {
var config = params ? {'params': params} : {};
return httpService.get(apiPassthroughUrl + 'v2/reverse/floatingips', config)
.error(function () {
toastService.add('error', gettext('Unable to retrieve the floating ip PTRs.'));
});
}
function get(id, params) {
var config = params ? {'params': params} : {};
return httpService.get(apiPassthroughUrl + 'v2/reverse/floatingips/' + id, config)
.error(function () {
toastService.add('error', gettext('Unable to get the floating ip PTR ' + id));
});
}
/**
* @name set
* @description
* Set a floating ip PTR record
*
* @param {string} floatingIpID - ID of PTR record to unset
* @param {Object} data
* Specifies the PTR information to set
*
* @returns {Object} The updated DNS floating IP object
*/
function set(floatingIpID, data) {
// The update API will not accept extra data. Restrict the input to only the allowed
// fields
var apiData = {
ptrdname: data.ptrdname,
description: data.description,
ttl: data.ttl
};
return httpService.patch(apiPassthroughUrl + 'v2/reverse/floatingips/' + floatingIpID, apiData)
.error(function () {
toastService.add('error', gettext('Unable to set the floating IP PTR record.'));
})
}
/**
* @name unset
* @description
* Unset a floating ip PTR record
*
* @param {string} floatingIpID - ID of PTR record to unset
*
* @returns {Object} The updated DNS floating IP object
*/
function unset(floatingIpID) {
// Unset is just a special case of 'set'
return set(floatingIpID, {
ptrdname: null,
description: null,
ttl: null
})
}
}
}());

View File

@ -0,0 +1,66 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
/**
* @ngdoc overview
* @ngname designatedashboard.resources.os-designate-floatingip.details
*
* @description
* Provides details features for floating IPs.
*/
angular.module('designatedashboard.resources.os-designate-floatingip.details',
['horizon.framework.conf', 'horizon.app.core'])
.run(run);
run.$inject = [
'designatedashboard.resources.os-designate-floatingip.resourceType',
'designatedashboard.resources.os-designate-floatingip.api',
'designatedashboard.resources.os-designate-floatingip.basePath',
'horizon.framework.conf.resource-type-registry.service'
];
function run(
resourceTypeName,
api,
basePath,
registry
) {
var resourceType = registry.getResourceType(resourceTypeName);
resourceType
.setLoadFunction(loadFunction)
.setSummaryTemplateUrl(basePath + 'details/drawer.html')
.setItemNameFunction(itemNameFunction);
resourceType.detailsViews
.prepend({
id: 'floatingIpDetailsOverview',
name: gettext('Overview'),
template: basePath + 'details/overview.html'
}, 0);
function loadFunction(identifier) {
return api.get(identifier);
}
function itemNameFunction(floatingIp) {
return floatingIp.address;
}
}
})();

View File

@ -0,0 +1,10 @@
<hz-resource-property-list
ng-if="item"
resource-type-name="OS::Designate::FloatingIp"
item="item"
cls="dl-horizontal"
property-groups="[
['description'],
['id']
]">
</hz-resource-property-list>

View File

@ -0,0 +1,46 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
"use strict";
angular
.module('designatedashboard.resources.os-designate-floatingip.details')
.controller('designatedashboard.resources.os-designate-floatingip.details.overviewController', controller);
controller.$inject = [
'designatedashboard.resources.os-designate-floatingip.resourceType',
'horizon.framework.conf.resource-type-registry.service',
'$scope'
];
function controller(
resourceTypeCode,
registry,
$scope
) {
var ctrl = this;
ctrl.item;
ctrl.resourceType = registry.getResourceType(resourceTypeCode);
$scope.context.loadPromise.then(onGetResponse);
function onGetResponse(response) {
ctrl.item = response.data;
}
}
})();

View File

@ -0,0 +1,11 @@
<div ng-controller="designatedashboard.resources.os-designate-floatingip.details.overviewController as ctrl">
<hz-resource-property-list
ng-if="ctrl.item"
resource-type-name="OS::Designate::FloatingIp"
item="ctrl.item"
cls="dl-horizontal"
property-groups="[
['ptrdname', 'description', 'id', 'ttl', 'status', 'action']
]">
</hz-resource-property-list>
</div>

View File

@ -0,0 +1,156 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
/**
* @ngdoc overview
* @ngname designatedashboard.resources.os-designate-floatingip
*
* @description
* Provides all of the services and widgets required
* to support and display DNS (designate) floating ip related content.
*/
angular
.module('designatedashboard.resources.os-designate-floatingip', [
'ngRoute',
'designatedashboard.resources.os-designate-floatingip.actions',
'designatedashboard.resources.os-designate-floatingip.details'
])
.constant(
'designatedashboard.resources.os-designate-floatingip.resourceType',
'OS::Designate::FloatingIp')
.config(config)
.run(run);
config.$inject = [ '$provide', '$windowProvider' ];
function config($provide, $windowProvider) {
var path = $windowProvider.$get().STATIC_URL + 'designatedashboard/resources/os-designate-floatingip/';
$provide.constant('designatedashboard.resources.os-designate-floatingip.basePath', path);
}
run.$inject = [
'horizon.app.core.detailRoute',
'horizon.framework.conf.resource-type-registry.service',
'designatedashboard.resources.os-designate-floatingip.api',
'designatedashboard.resources.os-designate-floatingip.resourceType',
'designatedashboard.resources.util'
];
function run(
detailRoute,
registry,
api,
resourceTypeString,
util)
{
var resourceType = registry.getResourceType(resourceTypeString);
resourceType
.setNames(gettext('Floating IP'), gettext('Floating IPs'))
.setListFunction(listFloatingIps)
.setProperty('id', {
label: gettext('ID')
})
.setProperty('ptrdname', {
label: gettext('PTR Domain Name'),
filters: ['noName']
})
.setProperty('description', {
label: gettext('Description'),
filters: ['noName']
})
.setProperty('ttl', {
label: gettext('Time To Live'),
filters: ['noValue']
})
.setProperty('address', {
label: gettext('Address'),
filters: ['noName']
})
.setProperty('status', {
label: gettext('Status'),
filters: ['lowercase', 'noName'],
values: util.statusMap()
})
.setProperty('action', {
label: gettext('Action'),
filters: ['lowercase', 'noName'],
values: util.actionMap()
});
resourceType
.tableColumns
.append({
id: 'address',
priority: 1,
sortDefault: true,
template: '<a ng-href="{$ \'' + detailRoute + 'OS::Designate::FloatingIp/\' + item.id $}">{$ item.address $}</a>'
})
.append({
id: 'ptrdname',
filters: ['noValue'],
priority: 1,
})
.append({
id: 'status',
filters: ['lowercase'],
values: util.statusMap(),
priority: 2
});
resourceType
.filterFacets
.append({
label: gettext('Address'),
name: 'address',
isServer: false,
singleton: true,
persistent: false
})
.append({
label: gettext('PTR Domain Name'),
name: 'ptrdname',
isServer: false,
singleton: true,
persistent: false
})
.append({
label: gettext('Status'),
name: 'status',
isServer: false,
singleton: true,
persistent: false,
options: [
{label: gettext('Active'), key: 'active'},
{label: gettext('Pending'), key: 'pending'}
]
});
function listFloatingIps() {
return api.list().then(function onList(response) {
// listFunctions are expected to return data in "items"
response.data.items = response.data.floatingips;
util.addTimestampIds(response.data.items);
return response;
});
}
}
})();

View File

@ -0,0 +1,79 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function () {
'use strict';
/**
* @ngdoc overview
* @ngname designatedashboard.resources.os-designate-recordset.actions
*
* @description
* Provides all of the actions for DNS Recordsets.
*/
angular.module('designatedashboard.resources.os-designate-recordset.actions', [
'horizon.framework.conf',
'horizon.app.core'
])
.run(run);
run.$inject = [
'horizon.framework.conf.resource-type-registry.service',
'designatedashboard.resources.os-designate-recordset.resourceType',
'designatedashboard.resources.os-designate-recordset.actions.create',
'designatedashboard.resources.os-designate-recordset.actions.delete',
'designatedashboard.resources.os-designate-recordset.actions.update'
];
function run(registry,
resourceTypeString,
createAction,
deleteAction,
updateAction) {
var resourceType = registry.getResourceType(resourceTypeString);
resourceType
.itemActions
.append({
id: 'updateRecordset',
service: updateAction,
template: {
text: gettext('Update')
}
})
.append({
id: 'deleteRecordset',
service: deleteAction,
template: {
text: gettext('Delete'),
type: 'delete'
}
});
// Append a record set view to the zones actions
var zoneResourceType = registry.getResourceType("OS::Designate::Zone");
zoneResourceType
.itemActions
.append({
id: 'createRecordset',
service: createAction,
template: {
text: gettext('Create Record Set')
}
});
}
})();

View File

@ -0,0 +1,165 @@
/**
*
* (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use self file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function () {
'use strict';
angular
.module('designatedashboard.resources.os-designate-recordset.actions')
.factory('designatedashboard.resources.os-designate-recordset.actions.common-forms', service);
service.$inject = [
'designatedashboard.resources.os-designate-recordset.editableTypes',
'designatedashboard.resources.os-designate-recordset.typeMap'
];
/**
* Service to return a schema form config for action forms. Especially useful for forms
* like create and update that differ only in the readonly state of certain form fields.
*
* @returns {object} A schema form config
*/
function service(editableTypes, typeMap) {
var service = {
getCreateFormConfig: getCreateFormConfig,
getUpdateFormConfig: getUpdateFormConfig
};
return service;
/////////////////
/**
* Returns the create form config
* @returns {{schema, form, model}|*}
*/
function getCreateFormConfig() {
return getCreateUpdateFormConfig(false);
}
/**
* Return the update form config
* @returns {{schema, form, model}|*}
*/
function getUpdateFormConfig() {
return getCreateUpdateFormConfig(true);
}
/**
* Return the create/update form. The two forms are identical except for
* during update, some fields are read-only.
*
* @param readonly - sets readonly value on form fields that change between update and create
* @returns {object} a schema form config, including default model
*/
function getCreateUpdateFormConfig(readonly) {
return {
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"pattern": /^.+\.$/
},
"description": {
"type": "string"
},
"type": {
"type": "string",
"enum": editableTypes
},
"ttl": {
"type": "integer",
"minimum": 1,
"maximum": 2147483647
},
"records": {
"type": "array",
"items": {
"type": "object",
"properties": {
"record": {
"type": "string"
}
}
},
"minItems": 1,
"uniqueItems": true
}
}
},
"form": [
{
"key": "type",
"readonly": readonly,
"title": gettext("Type"),
"description": gettext("Select the type of record set"),
"type": "select",
"titleMap": editableTypes.map(function toTitleMap(type) {
return {
"value": type,
"name": typeMap[type]
}
}),
"required": true
},
{
"key": "name",
"readonly": readonly,
"type": "text",
"title": gettext("Name"),
"description": gettext("DNS name for the record set, ending in '.'"),
"validationMessage": gettext("DNS name must end with '.'"),
"placeholder": "www.example.com.",
"required": true
},
{
"key": "description",
"type": "textarea",
"title": gettext("Description"),
"description": gettext("Details about the zone.")
},
{
"key": "ttl",
"title": gettext("TTL"),
"description": gettext("Time To Live in seconds."),
"type": "number",
"required": true
},
{
"key": "records",
"title": gettext("Records"),
"type": "array",
"description": gettext("Records for the record set."),
"add": gettext("Add Record"),
"items": [
{
"key": "records[].record",
"title": gettext("Record")
}
],
"required": true
}
],
"model": {
"type": "A",
"ttl": 3600
}
};
}
}
})();

View File

@ -0,0 +1,132 @@
/**
*
* (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use self file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function () {
'use strict';
angular
.module('designatedashboard.resources.os-designate-recordset.actions')
.factory('designatedashboard.resources.os-designate-recordset.actions.create', action);
action.$inject = [
'$q',
'designatedashboard.resources.os-designate-recordset.actions.common-forms',
'designatedashboard.resources.os-designate-recordset.api',
'designatedashboard.resources.os-designate-recordset.resourceType',
'horizon.app.core.openstack-service-api.policy',
'horizon.app.core.openstack-service-api.serviceCatalog',
'horizon.framework.conf.resource-type-registry.service',
'horizon.framework.widgets.form.ModalFormService',
'horizon.framework.widgets.toast.service',
'horizon.framework.widgets.modal-wait-spinner.service'
];
/**
* @ngDoc factory
* @name designatedashboard.resources.os-designate-recordset.actions.create
*
* @Description
* Brings up the Create Record Set modal.
*/
function action($q,
forms,
api,
resourceTypeName,
policy,
serviceCatalog,
registry,
schemaFormModalService,
toast,
waitSpinner) {
var createRecordSetPolicy, dnsServiceEnabled;
var title = gettext("Create Record Set");
var message = {
success: gettext('Record Set %s was successfully created.')
};
var service = {
initScope: initScope,
allowed: allowed,
perform: perform
};
return service;
/////////////////
function initScope() {
createRecordSetPolicy = policy.ifAllowed({rules: [['dns', 'create_recordset']]});
dnsServiceEnabled = serviceCatalog.ifTypeEnabled('dns');
}
function allowed(item) {
return $q.all([
createRecordSetPolicy,
dnsServiceEnabled
]);
}
function perform(item) {
var formConfig = forms.getCreateFormConfig();
// Store the zone ID so it can be used on submit
formConfig.model.zoneId = item.id;
formConfig.title = title;
return schemaFormModalService.open(formConfig).then(onSubmit, onCancel);
}
function onSubmit(context) {
var model = angular.copy(context.model);
var zoneId = model.zoneId;
delete model.zoneId;
// schema form doesn't appear to support populating arrays directly
// Map the records objects to simple array of records
var records = context.model.records.map(function (item) {
return item.record;
});
model.records = records;
waitSpinner.showModalSpinner(gettext('Creating Record Set'));
return api.create(zoneId, model).then(onSuccess, onFailure);
}
function onCancel() {
waitSpinner.hideModalSpinner();
}
function onSuccess(response) {
waitSpinner.hideModalSpinner();
var zone = response.data;
toast.add('success', interpolate(message.success, [zone.name]));
// To make the result of this action generically useful, reformat the return
// from the deleteModal into a standard form
return {
created: [{type: resourceTypeName, id: zone.id}],
updated: [],
deleted: [],
failed: []
};
}
function onFailure() {
waitSpinner.hideModalSpinner();
}
}
})();

View File

@ -0,0 +1,182 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use self file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
angular
.module('designatedashboard.resources.os-designate-recordset.actions')
.factory('designatedashboard.resources.os-designate-recordset.actions.delete', action);
action.$inject = [
'$q',
'designatedashboard.resources.os-designate-recordset.api',
'designatedashboard.resources.os-designate-recordset.editableTypes',
'designatedashboard.resources.os-designate-recordset.resourceType',
'horizon.app.core.openstack-service-api.policy',
'horizon.framework.util.actions.action-result.service',
'horizon.framework.util.i18n.gettext',
'horizon.framework.util.q.extensions',
'horizon.framework.widgets.modal.deleteModalService',
'horizon.framework.widgets.toast.service'
];
/*
* @ngdoc factory
* @name designatedashboard.resources.os-designate-recordset.actions.delete
*
* @Description
* Brings up the delete recordset confirmation modal dialog.
* On submit, delete given recordset.
* On cancel, do nothing.
*/
function action(
$q,
recordsetApi,
editableTypes,
resourceType,
policy,
actionResultService,
gettext,
$qExtensions,
deleteModal,
toast
) {
var scope, context, deletePromise;
var notAllowedMessage = gettext("You are not allowed to delete record sets: %s");
var allowedRecordsets = [];
var service = {
initScope: initScope,
allowed: allowed,
perform: perform
};
return service;
//////////////
function initScope(newScope) {
scope = newScope;
context = { };
deletePromise = policy.ifAllowed({rules: [['dns', 'delete_recordset']]});
}
function perform(items) {
var recordsets = angular.isArray(items) ? items : [items];
context.labels = labelize(recordsets.length);
context.deleteEntity = deleteRecordSet;
return $qExtensions.allSettled(recordsets.map(checkPermission)).then(afterCheck);
}
function allowed(recordset) {
// only row actions pass in recordset
// otherwise, assume it is a batch action
if (recordset) {
return $q.all([
deletePromise,
editableRecordType(recordset)
]);
} else {
return policy.ifAllowed({ rules: [['dns', 'delete_recordset']] });
}
}
function checkPermission(recordset) {
return {promise: allowed(recordset), context: recordset};
}
function afterCheck(result) {
var outcome = $q.reject(); // Reject the promise by default
if (result.fail.length > 0) {
toast.add('error', getMessage(notAllowedMessage, result.fail));
outcome = $q.reject(result.fail);
}
if (result.pass.length > 0) {
// Remember the record sets we are allowed to delete so that on delete modal submit
// we can map the recordset ID back to the full recordset. Then we can fetch the
// corresponding zone ID
allowedRecordsets = result.pass.map(getEntity)
outcome = deleteModal.open(scope, allowedRecordsets, context).then(createResult);
}
return outcome;
}
function createResult(deleteModalResult) {
// To make the result of this action generically useful, reformat the return
// from the deleteModal into a standard form
var actionResult = actionResultService.getActionResult();
deleteModalResult.pass.forEach(function markDeleted(item) {
actionResult.deleted(resourceType, getEntity(item).id);
});
deleteModalResult.fail.forEach(function markFailed(item) {
actionResult.failed(resourceType, getEntity(item).id);
});
return actionResult.result;
}
function labelize(count) {
return {
title: ngettext(
'Confirm Delete Record Set',
'Confirm Delete Record Sets', count),
message: ngettext(
'You have selected "%s". Deleted record set is not recoverable.',
'You have selected "%s". Deleted record sets are not recoverable.', count),
submit: ngettext(
'Delete Record Set',
'Delete Record Sets', count),
success: ngettext(
'Deleted Record Set: %s.',
'Deleted Record Sets: %s.', count),
error: ngettext(
'Unable to delete Record Set: %s.',
'Unable to delete Record Sets: %s.', count)
};
}
function editableRecordType(recordset) {
return $qExtensions.booleanAsPromise(
editableTypes.indexOf(recordset.type) > -1
);
}
function deleteRecordSet(recordSetId) {
var recordSet = allowedRecordsets.find(function(element) {
return element.id === recordSetId;
})
return recordsetApi.deleteRecordSet(recordSet.zone_id, recordSet.id);
}
function getMessage(message, entities) {
return interpolate(message, [entities.map(getName).join(", ")]);
}
function getName(result) {
return getEntity(result).name;
}
function getEntity(result) {
return result.context;
}
}
})();

View File

@ -0,0 +1,159 @@
/**
*
* (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use self file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function () {
'use strict';
angular
.module('designatedashboard.resources.os-designate-recordset.actions')
.factory('designatedashboard.resources.os-designate-recordset.actions.update', action);
action.$inject = [
'$q',
'designatedashboard.resources.util',
'designatedashboard.resources.os-designate-recordset.actions.common-forms',
'designatedashboard.resources.os-designate-recordset.api',
'designatedashboard.resources.os-designate-recordset.editableTypes',
'designatedashboard.resources.os-designate-recordset.resourceType',
'horizon.app.core.openstack-service-api.policy',
'horizon.app.core.openstack-service-api.serviceCatalog',
'horizon.framework.util.q.extensions',
'horizon.framework.widgets.form.ModalFormService',
'horizon.framework.widgets.toast.service',
'horizon.framework.widgets.modal-wait-spinner.service'
];
/**
* @ngDoc factory
* @name designatedashboard.resources.os-designate-recordset.actions.update
*
* @Description
* Brings up the Update modal.
*/
function action($q,
util,
forms,
api,
editableTypes,
resourceTypeName,
policy,
serviceCatalog,
$qExtensions,
schemaFormModalService,
toast,
waitSpinner) {
var updateRecordSetPolicy, dnsServiceEnabled;
var title = gettext("Update Record Set");
var message = {
success: gettext('Record Set %s was successfully updated.')
};
var service = {
initScope: initScope,
allowed: allowed,
perform: perform
};
return service;
/////////////////
function initScope() {
updateRecordSetPolicy = policy.ifAllowed({rules: [['dns', 'update_recordset']]});
dnsServiceEnabled = serviceCatalog.ifTypeEnabled('dns');
}
function allowed(recordset) {
// only supports row action (exactly 1 recordset)
if (recordset) {
return $q.all([
updateRecordSetPolicy,
util.notDeleted(recordset),
util.notPending(recordset),
editableRecordType(recordset)
]);
} else {
return false;
}
}
function editableRecordType(recordset) {
return $qExtensions.booleanAsPromise(
editableTypes.indexOf(recordset.type) > -1
);
}
function perform(item) {
var formConfig = forms.getUpdateFormConfig();
formConfig.title = title;
formConfig.model = util.getModel(formConfig.form, item);
// Append the id and zoneId so it can be used on submit
formConfig.model.id = item.id;
formConfig.model.zoneId = item.zone_id;
// schema form doesn't appear to support populating the records array directly
// Map the records objects to record objects
if (item.hasOwnProperty("records")) {
var records = item.records.map(function (item) {
return {"record": item}
});
formConfig.model.records = records;
}
return schemaFormModalService.open(formConfig).then(onSubmit, onCancel);
}
function onSubmit(context) {
var model = angular.copy(context.model);
// schema form doesn't appear to support populating the records array directly
// Map the records objects to simple array of records
if (context.model.hasOwnProperty("records")) {
var records = context.model.records.map(function (item) {
return item.record;
});
model.records = records;
}
waitSpinner.showModalSpinner(gettext('Updating Record Set'));
return api.update(model.zoneId, model.id, model).then(onSuccess, onFailure);
}
function onCancel() {
waitSpinner.hideModalSpinner();
}
function onSuccess(response) {
waitSpinner.hideModalSpinner();
var recordset = response.data;
toast.add('success', interpolate(message.success, [recordset.name]));
// To make the result of this action generically useful, reformat the return
// from the deleteModal into a standard form
return {
created: [],
updated: [{type: resourceTypeName, id: recordset.id}],
deleted: [],
failed: []
};
}
function onFailure() {
waitSpinner.hideModalSpinner();
}
}
})();

View File

@ -0,0 +1,136 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function () {
'use strict';
angular
.module('designatedashboard.resources.os-designate-recordset')
.factory('designatedashboard.resources.os-designate-recordset.api', apiService);
apiService.$inject = [
'$q',
'designatedashboard.apiPassthroughUrl',
'horizon.framework.util.http.service',
'horizon.framework.widgets.toast.service'
];
/**
* @ngdoc service
* @param {Object} httpService
* @param {Object} toastService
* @name apiService
* @description Provides direct access to Designate Record Set APIs.
* @returns {Object} The service
*/
function apiService($q, apiPassthroughUrl, httpService, toastService) {
var service = {
get: get,
list: list,
deleteRecordSet: deleteRecordSet,
create: create,
update: update
};
return service;
///////////////
/**
* @name list
* @description
* Get a list of record sets.
*
* The listing result is an object with property "items." Each item is
* a record set.
*
* @param {Object} params
* Query parameters. Optional.
*
* @returns {Object} The result of the API call
*/
function list(zoneId, params) {
return httpService.get(apiPassthroughUrl + 'v2/zones/' + zoneId + '/recordsets/', params)
.error(function () {
toastService.add('error', gettext('Unable to retrieve the record sets.'));
});
}
/**
* @name get
* @description
* Get a single record set by ID.
*
* @param {string} zoneId
* Specifies the id of the zone containing the record set to request.
*
* @param {string} recordSetId
* Specifies the id of the record set to request.
*
* @returns {Object} The result of the API call
*/
function get(zoneId, recordSetId) {
// Unfortunately routed-details-view is not happy when load fails, which is
// common when then delete action removes a record set. Mask this failure by
// always returning a successful promise instead of terminating the $http promise
// in the .error handler.
return httpService.get(apiPassthroughUrl + 'v2/zones/' + zoneId + '/recordsets/' + recordSetId + '/')
.then(undefined, function onError() {
toastService.add('error', gettext('Unable to retrieve the record set.'));
return $q.when({});
});
}
/**
* @name delete
* @description
* Delete a single record set by ID
* @param {string} zoneId
* The id of the zone containing the recordset
*
* @param {string} recordSetId
* The id of the recordset within the zone
*
* @returns {*}
*/
function deleteRecordSet(zoneId, recordSetId) {
return httpService.delete(apiPassthroughUrl + 'v2/zones/' + zoneId + '/recordsets/' + recordSetId + '/')
.error(function () {
toastService.add('error', gettext('Unable to delete the record set.'));
});
}
function create(zoneId, data) {
return httpService.post(apiPassthroughUrl + 'v2/zones/' + zoneId + '/recordsets/', data)
.error(function () {
toastService.add('error', gettext('Unable to create the record set.'));
});
}
function update(zoneId, recordSetId, data) {
// The update API will not accept extra data. Restrict the input to only the allowed
// fields
var apiData = {
ttl: data.ttl,
description: data.description,
records: data.records
};
return httpService.put(apiPassthroughUrl + 'v2/zones/' + zoneId + '/recordsets/' + recordSetId, apiData)
.error(function () {
toastService.add('error', gettext('Unable to update the record set.'));
});
}
}
}());

View File

@ -0,0 +1,109 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
/**
* @ngdoc overview
* @ngname designatedashboard.resources.os-designate-recordset.details
*
* @description
* Provides details features for record sets.
*/
angular.module('designatedashboard.resources.os-designate-recordset.details',
['horizon.framework.conf', 'horizon.app.core'])
.run(run);
run.$inject = [
'designatedashboard.resources.os-designate-recordset.resourceType',
'designatedashboard.resources.os-designate-recordset.api',
'designatedashboard.resources.os-designate-recordset.basePath',
'horizon.framework.conf.resource-type-registry.service',
];
function run(
recordSetResourceType,
recordSetApi,
basePath,
registry
) {
var resourceType = registry.getResourceType(recordSetResourceType);
resourceType
.setLoadFunction(loadFunction)
.setPathGenerator(pathGenerator)
.setPathParser(pathParser)
.setSummaryTemplateUrl(basePath + 'details/drawer.html');
/**
*
* @param identifier
* The object returned by the pathParser containing the zone ID and record set ID to load
*/
function loadFunction(identifier) {
return recordSetApi.get(identifier.zoneId, identifier.recordSetId);
}
/**
* Because a record set is contained by a zone, we implement a custom
* pathGenerator to encode the zone ID and record set ID for the generic
* details panel.
*
* @param item
* A record set
*
* @returns {string} In format "<zone_id>/<recordset_id>"
*/
function pathGenerator(item) {
return item.zone_id + '/' + item.id;
}
/**
* Given a path, extract the zone and record set ids
*
* @param path
* created by pathGenerator
*
* @returns {{zoneId: *, recordSetId: *}}
* The identifier to pass to the load function needed to uniquely identify
* a record set.
*/
function pathParser(path) {
var split = path.split('/');
return {
zoneId: split[0],
recordSetId: split[1]
}
}
resourceType.detailsViews
.prepend({
id: 'recordsetDetailsOverview',
name: gettext('Overview'),
template: basePath + 'details/overview.html',
}, 0);
// Append a record set view to the zones resource view
var zoneResourceType = registry.getResourceType("OS::Designate::Zone");
zoneResourceType.detailsViews
.append({
id: 'zoneRecordSets',
name: gettext('Record Sets'),
template: basePath + 'details/zone-recordsets.html',
});
}
})();

View File

@ -0,0 +1,10 @@
<hz-resource-property-list
ng-if="item"
resource-type-name="OS::Designate::RecordSet"
item="item"
cls="dl-horizontal"
property-groups="[
['records', 'notes', 'description'],
['id']
]">
</hz-resource-property-list>

View File

@ -0,0 +1,46 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
"use strict";
angular
.module('designatedashboard.resources.os-designate-recordset')
.controller('designatedashboard.resources.os-designate-recordset.detailController', controller);
controller.$inject = [
'designatedashboard.resources.os-designate-recordset.resourceType',
'horizon.framework.conf.resource-type-registry.service',
'$scope'
];
function controller(
resourceTypeCode,
registry,
$scope
) {
var ctrl = this;
ctrl.item = {};
ctrl.resourceType = registry.getResourceType(resourceTypeCode);
$scope.context.loadPromise.then(onGetResponse);
function onGetResponse(response) {
ctrl.item = response.data;
}
}
})();

View File

@ -0,0 +1,45 @@
<div ng-controller="designatedashboard.resources.os-designate-recordset.detailController as ctrl">
<div class="row">
<div class="col-md-6 detail">
<h3 translate>Details</h3>
<hr>
<hz-resource-property-list
ng-if="ctrl.item"
resource-type-name="OS::Designate::RecordSet"
item="ctrl.item"
cls="dl-horizontal"
property-groups="[
['id', 'type', 'name', 'records', 'notes', 'description', 'ttl', 'version', 'action', 'status']
]">
</hz-resource-property-list>
</div>
<div class="col-md-6 detail">
<h3 translate>Associations</h3>
<hr>
<hz-resource-property-list
ng-if="ctrl.item"
resource-type-name="OS::Designate::RecordSet"
item="ctrl.item"
cls="dl-horizontal"
property-groups="[
['zone_id', 'zone_name', 'project_id']
]">
</hz-resource-property-list>
</div>
</div>
<div class="row">
<div class="col-md-6 detail">
<h3 translate>Modification Times</h3>
<hr>
<hz-resource-property-list
ng-if="ctrl.item"
resource-type-name="OS::Designate::RecordSet"
item="ctrl.item"
cls="dl-horizontal"
property-groups="[
['created_at', 'updated_at']
]">
</hz-resource-property-list>
</div>
</div>
</div>

View File

@ -0,0 +1,39 @@
/**
* (c) Copyright 2016 Hewlett Packard Enterprise Development LP
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
"use strict";
angular
.module('designatedashboard.resources.os-designate-recordset')
.controller('designatedashboard.resources.os-designate-recordset.zoneRecordSetsController', controller);
controller.$inject = [
'$scope',
'designatedashboard.resources.os-designate-recordset.resourceType'
];
function controller(
$scope,
resourceTypeName
) {
var ctrl = this;
ctrl.item = {};
ctrl.resourceTypeName = resourceTypeName;
ctrl.extraListParams = { zoneId: $scope.context.identifier };
}
})();

View File

@ -0,0 +1,8 @@
<div
ng-controller="designatedashboard.resources.os-designate-recordset.zoneRecordSetsController as ctrl">
<hz-resource-table
resource-type-name="{$ ctrl.resourceTypeName $}"
list-function-extra-params="ctrl.extraListParams"
track-by="_timestampId">
</hz-resource-table>
</div>

Some files were not shown because too many files have changed in this diff Show More