summaryrefslogtreecommitdiff
path: root/openstack_dashboard
diff options
context:
space:
mode:
authorGabriel Hurley <gabriel@strikeawe.com>2012-10-04 15:43:40 -0700
committerGabriel Hurley <gabriel@strikeawe.com>2012-10-11 11:47:50 -0700
commitcb8e7c1f8f0b238b88253cd6d82092cbe530ba9e (patch)
tree9ee3463e05ae6cf2f9cee5309a648538471c02b9 /openstack_dashboard
parentef1e1d9b7a1fd4140518318ead8b7174a6a434ab (diff)
downloadhorizon-cb8e7c1f8f0b238b88253cd6d82092cbe530ba9e.tar.gz
Splits OpenStack Dashboard bits from framework app code.
Moves everything OpenStack-specific (dashboards, apis, etc.) into the openstack_dashboard project, achieving a much cleaner separation between the project-specific code and the generic Horizon framework code. Change-Id: I7235b41d449b26c980668fc3eb4360b24508717b
Diffstat (limited to 'openstack_dashboard')
-rw-r--r--openstack_dashboard/api/__init__.py39
-rw-r--r--openstack_dashboard/api/base.py118
-rw-r--r--openstack_dashboard/api/glance.py98
-rw-r--r--openstack_dashboard/api/keystone.py291
-rw-r--r--openstack_dashboard/api/nova.py587
-rw-r--r--openstack_dashboard/api/quantum.py261
-rw-r--r--openstack_dashboard/api/swift.py265
-rw-r--r--openstack_dashboard/context_processors.py63
-rw-r--r--openstack_dashboard/dashboards/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/admin/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/admin/dashboard.py37
-rw-r--r--openstack_dashboard/dashboards/admin/flavors/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/admin/flavors/forms.py96
-rw-r--r--openstack_dashboard/dashboards/admin/flavors/panel.py33
-rw-r--r--openstack_dashboard/dashboards/admin/flavors/tables.py54
-rw-r--r--openstack_dashboard/dashboards/admin/flavors/templates/flavors/_create.html25
-rw-r--r--openstack_dashboard/dashboards/admin/flavors/templates/flavors/_edit.html26
-rw-r--r--openstack_dashboard/dashboards/admin/flavors/templates/flavors/create.html11
-rw-r--r--openstack_dashboard/dashboards/admin/flavors/templates/flavors/edit.html11
-rw-r--r--openstack_dashboard/dashboards/admin/flavors/templates/flavors/index.html11
-rw-r--r--openstack_dashboard/dashboards/admin/flavors/tests.py81
-rw-r--r--openstack_dashboard/dashboards/admin/flavors/urls.py29
-rw-r--r--openstack_dashboard/dashboards/admin/flavors/views.py82
-rw-r--r--openstack_dashboard/dashboards/admin/images/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/admin/images/forms.py26
-rw-r--r--openstack_dashboard/dashboards/admin/images/panel.py33
-rw-r--r--openstack_dashboard/dashboards/admin/images/tables.py46
-rw-r--r--openstack_dashboard/dashboards/admin/images/templates/images/_update.html25
-rw-r--r--openstack_dashboard/dashboards/admin/images/templates/images/index.html11
-rw-r--r--openstack_dashboard/dashboards/admin/images/templates/images/update.html12
-rw-r--r--openstack_dashboard/dashboards/admin/images/tests.py97
-rw-r--r--openstack_dashboard/dashboards/admin/images/urls.py30
-rw-r--r--openstack_dashboard/dashboards/admin/images/views.py68
-rw-r--r--openstack_dashboard/dashboards/admin/instances/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/admin/instances/panel.py34
-rw-r--r--openstack_dashboard/dashboards/admin/instances/tables.py100
-rw-r--r--openstack_dashboard/dashboards/admin/instances/templates/instances/index.html11
-rw-r--r--openstack_dashboard/dashboards/admin/instances/tests.py140
-rw-r--r--openstack_dashboard/dashboards/admin/instances/urls.py34
-rw-r--r--openstack_dashboard/dashboards/admin/instances/views.py84
-rw-r--r--openstack_dashboard/dashboards/admin/models.py23
-rw-r--r--openstack_dashboard/dashboards/admin/networks/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/admin/networks/forms.py90
-rw-r--r--openstack_dashboard/dashboards/admin/networks/panel.py29
-rw-r--r--openstack_dashboard/dashboards/admin/networks/ports/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/admin/networks/ports/forms.py93
-rw-r--r--openstack_dashboard/dashboards/admin/networks/ports/tables.py85
-rw-r--r--openstack_dashboard/dashboards/admin/networks/ports/tabs.py49
-rw-r--r--openstack_dashboard/dashboards/admin/networks/ports/urls.py28
-rw-r--r--openstack_dashboard/dashboards/admin/networks/ports/views.py99
-rw-r--r--openstack_dashboard/dashboards/admin/networks/subnets/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/admin/networks/subnets/forms.py53
-rw-r--r--openstack_dashboard/dashboards/admin/networks/subnets/tables.py83
-rw-r--r--openstack_dashboard/dashboards/admin/networks/subnets/urls.py29
-rw-r--r--openstack_dashboard/dashboards/admin/networks/subnets/views.py103
-rw-r--r--openstack_dashboard/dashboards/admin/networks/tables.py82
-rw-r--r--openstack_dashboard/dashboards/admin/networks/templates/networks/_create.html25
-rw-r--r--openstack_dashboard/dashboards/admin/networks/templates/networks/_update.html24
-rw-r--r--openstack_dashboard/dashboards/admin/networks/templates/networks/create.html11
-rw-r--r--openstack_dashboard/dashboards/admin/networks/templates/networks/index.html21
-rw-r--r--openstack_dashboard/dashboards/admin/networks/templates/networks/ports/_create.html25
-rw-r--r--openstack_dashboard/dashboards/admin/networks/templates/networks/ports/_update.html29
-rw-r--r--openstack_dashboard/dashboards/admin/networks/templates/networks/ports/create.html11
-rw-r--r--openstack_dashboard/dashboards/admin/networks/templates/networks/ports/update.html11
-rw-r--r--openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/_create.html25
-rw-r--r--openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/_update.html33
-rw-r--r--openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/create.html11
-rw-r--r--openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/index.html11
-rw-r--r--openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/update.html11
-rw-r--r--openstack_dashboard/dashboards/admin/networks/templates/networks/update.html11
-rw-r--r--openstack_dashboard/dashboards/admin/networks/tests.py805
-rw-r--r--openstack_dashboard/dashboards/admin/networks/urls.py47
-rw-r--r--openstack_dashboard/dashboards/admin/networks/views.py140
-rw-r--r--openstack_dashboard/dashboards/admin/overview/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/admin/overview/panel.py34
-rw-r--r--openstack_dashboard/dashboards/admin/overview/templates/overview/usage.csv9
-rw-r--r--openstack_dashboard/dashboards/admin/overview/templates/overview/usage.html22
-rw-r--r--openstack_dashboard/dashboards/admin/overview/tests.py97
-rw-r--r--openstack_dashboard/dashboards/admin/overview/urls.py29
-rw-r--r--openstack_dashboard/dashboards/admin/overview/views.py48
-rw-r--r--openstack_dashboard/dashboards/admin/projects/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/admin/projects/forms.py33
-rw-r--r--openstack_dashboard/dashboards/admin/projects/panel.py33
-rw-r--r--openstack_dashboard/dashboards/admin/projects/tables.py157
-rw-r--r--openstack_dashboard/dashboards/admin/projects/templates/projects/_add_user.html25
-rw-r--r--openstack_dashboard/dashboards/admin/projects/templates/projects/_create.html25
-rw-r--r--openstack_dashboard/dashboards/admin/projects/templates/projects/_create_user.html25
-rw-r--r--openstack_dashboard/dashboards/admin/projects/templates/projects/_quotas.html24
-rw-r--r--openstack_dashboard/dashboards/admin/projects/templates/projects/_update.html25
-rw-r--r--openstack_dashboard/dashboards/admin/projects/templates/projects/_update_members.html39
-rw-r--r--openstack_dashboard/dashboards/admin/projects/templates/projects/add_user.html11
-rw-r--r--openstack_dashboard/dashboards/admin/projects/templates/projects/create.html12
-rw-r--r--openstack_dashboard/dashboards/admin/projects/templates/projects/create_user.html12
-rw-r--r--openstack_dashboard/dashboards/admin/projects/templates/projects/index.html13
-rw-r--r--openstack_dashboard/dashboards/admin/projects/templates/projects/quotas.html11
-rw-r--r--openstack_dashboard/dashboards/admin/projects/templates/projects/update.html12
-rw-r--r--openstack_dashboard/dashboards/admin/projects/templates/projects/usage.csv11
-rw-r--r--openstack_dashboard/dashboards/admin/projects/templates/projects/usage.html14
-rw-r--r--openstack_dashboard/dashboards/admin/projects/templates/projects/users.html18
-rw-r--r--openstack_dashboard/dashboards/admin/projects/tests.py842
-rw-r--r--openstack_dashboard/dashboards/admin/projects/urls.py37
-rw-r--r--openstack_dashboard/dashboards/admin/projects/views.py203
-rw-r--r--openstack_dashboard/dashboards/admin/projects/workflows.py366
-rw-r--r--openstack_dashboard/dashboards/admin/quotas/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/admin/quotas/panel.py33
-rw-r--r--openstack_dashboard/dashboards/admin/quotas/tables.py38
-rw-r--r--openstack_dashboard/dashboards/admin/quotas/templates/quotas/index.html13
-rw-r--r--openstack_dashboard/dashboards/admin/quotas/tests.py1
-rw-r--r--openstack_dashboard/dashboards/admin/quotas/urls.py27
-rw-r--r--openstack_dashboard/dashboards/admin/quotas/views.py47
-rw-r--r--openstack_dashboard/dashboards/admin/services/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/admin/services/panel.py33
-rw-r--r--openstack_dashboard/dashboards/admin/services/tables.py50
-rw-r--r--openstack_dashboard/dashboards/admin/services/templates/services/index.html14
-rw-r--r--openstack_dashboard/dashboards/admin/services/tests.py36
-rw-r--r--openstack_dashboard/dashboards/admin/services/urls.py27
-rw-r--r--openstack_dashboard/dashboards/admin/services/views.py41
-rw-r--r--openstack_dashboard/dashboards/admin/users/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/admin/users/forms.py196
-rw-r--r--openstack_dashboard/dashboards/admin/users/panel.py33
-rw-r--r--openstack_dashboard/dashboards/admin/users/tables.py124
-rw-r--r--openstack_dashboard/dashboards/admin/users/templates/users/_create.html24
-rw-r--r--openstack_dashboard/dashboards/admin/users/templates/users/_update.html24
-rw-r--r--openstack_dashboard/dashboards/admin/users/templates/users/create.html12
-rw-r--r--openstack_dashboard/dashboards/admin/users/templates/users/index.html13
-rw-r--r--openstack_dashboard/dashboards/admin/users/templates/users/update.html12
-rw-r--r--openstack_dashboard/dashboards/admin/users/tests.py357
-rw-r--r--openstack_dashboard/dashboards/admin/users/urls.py28
-rw-r--r--openstack_dashboard/dashboards/admin/users/views.py112
-rw-r--r--openstack_dashboard/dashboards/admin/volumes/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/admin/volumes/panel.py14
-rw-r--r--openstack_dashboard/dashboards/admin/volumes/tables.py19
-rw-r--r--openstack_dashboard/dashboards/admin/volumes/templates/volumes/detail.html15
-rw-r--r--openstack_dashboard/dashboards/admin/volumes/templates/volumes/index.html13
-rw-r--r--openstack_dashboard/dashboards/admin/volumes/tests.py39
-rw-r--r--openstack_dashboard/dashboards/admin/volumes/urls.py8
-rw-r--r--openstack_dashboard/dashboards/admin/volumes/views.py39
-rw-r--r--openstack_dashboard/dashboards/project/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/floating_ips/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/floating_ips/forms.py47
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/floating_ips/tables.py130
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/floating_ips/tests.py177
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/floating_ips/urls.py29
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/floating_ips/views.py69
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/floating_ips/workflows.py115
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/keypairs/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/keypairs/forms.py66
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/keypairs/tables.py62
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/keypairs/tests.py163
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/keypairs/urls.py33
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/keypairs/views.py82
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/panel.py30
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/security_groups/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/security_groups/forms.py174
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/security_groups/tables.py109
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/security_groups/tests.py375
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/security_groups/urls.py30
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/security_groups/views.py121
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html33
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html7
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html11
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/index.html21
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html25
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html25
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html12
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html21
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html12
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html25
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html21
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html11
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html11
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/tests.py88
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/urls.py35
-rw-r--r--openstack_dashboard/dashboards/project/access_and_security/views.py84
-rw-r--r--openstack_dashboard/dashboards/project/containers/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/project/containers/browsers.py33
-rw-r--r--openstack_dashboard/dashboards/project/containers/forms.py164
-rw-r--r--openstack_dashboard/dashboards/project/containers/panel.py33
-rw-r--r--openstack_dashboard/dashboards/project/containers/tables.py270
-rw-r--r--openstack_dashboard/dashboards/project/containers/templates/containers/_copy.html24
-rw-r--r--openstack_dashboard/dashboards/project/containers/templates/containers/_create.html24
-rw-r--r--openstack_dashboard/dashboards/project/containers/templates/containers/_upload.html25
-rw-r--r--openstack_dashboard/dashboards/project/containers/templates/containers/copy.html13
-rw-r--r--openstack_dashboard/dashboards/project/containers/templates/containers/create.html11
-rw-r--r--openstack_dashboard/dashboards/project/containers/templates/containers/index.html13
-rw-r--r--openstack_dashboard/dashboards/project/containers/templates/containers/upload.html15
-rw-r--r--openstack_dashboard/dashboards/project/containers/tests.py238
-rw-r--r--openstack_dashboard/dashboards/project/containers/urls.py50
-rw-r--r--openstack_dashboard/dashboards/project/containers/views.py218
-rw-r--r--openstack_dashboard/dashboards/project/dashboard.py47
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/images/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/images/forms.py165
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/images/tables.py135
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/images/tabs.py45
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/images/tests.py96
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/images/urls.py34
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/images/views.py84
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/panel.py30
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/forms.py57
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/tables.py60
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/tests.py98
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/urls.py30
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/views.py63
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html33
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html68
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html24
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html11
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html16
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html11
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html19
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html25
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html42
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html11
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html15
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/tests.py170
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/urls.py35
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/views.py89
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/volume_snapshots/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/volume_snapshots/tables.py89
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/volume_snapshots/tabs.py49
-rw-r--r--openstack_dashboard/dashboards/project/images_and_snapshots/volume_snapshots/tests.py61
-rw-r--r--openstack_dashboard/dashboards/project/instances/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/project/instances/forms.py51
-rw-r--r--openstack_dashboard/dashboards/project/instances/panel.py29
-rw-r--r--openstack_dashboard/dashboards/project/instances/tables.py319
-rw-r--r--openstack_dashboard/dashboards/project/instances/tabs.py78
-rw-r--r--openstack_dashboard/dashboards/project/instances/templates/instances/_detail_log.html17
-rw-r--r--openstack_dashboard/dashboards/project/instances/templates/instances/_detail_overview.html98
-rw-r--r--openstack_dashboard/dashboards/project/instances/templates/instances/_detail_vnc.html10
-rw-r--r--openstack_dashboard/dashboards/project/instances/templates/instances/_instance_ips.html10
-rw-r--r--openstack_dashboard/dashboards/project/instances/templates/instances/_launch_customize_help.html3
-rw-r--r--openstack_dashboard/dashboards/project/instances/templates/instances/_launch_details_help.html53
-rw-r--r--openstack_dashboard/dashboards/project/instances/templates/instances/_launch_volumes_help.html3
-rw-r--r--openstack_dashboard/dashboards/project/instances/templates/instances/_update.html24
-rw-r--r--openstack_dashboard/dashboards/project/instances/templates/instances/detail.html15
-rw-r--r--openstack_dashboard/dashboards/project/instances/templates/instances/index.html11
-rw-r--r--openstack_dashboard/dashboards/project/instances/templates/instances/launch.html11
-rw-r--r--openstack_dashboard/dashboards/project/instances/templates/instances/update.html11
-rw-r--r--openstack_dashboard/dashboards/project/instances/tests.py980
-rw-r--r--openstack_dashboard/dashboards/project/instances/urls.py37
-rw-r--r--openstack_dashboard/dashboards/project/instances/views.py187
-rw-r--r--openstack_dashboard/dashboards/project/instances/workflows.py511
-rw-r--r--openstack_dashboard/dashboards/project/models.py23
-rw-r--r--openstack_dashboard/dashboards/project/networks/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/project/networks/forms.py56
-rw-r--r--openstack_dashboard/dashboards/project/networks/panel.py29
-rw-r--r--openstack_dashboard/dashboards/project/networks/ports/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/project/networks/ports/tables.py53
-rw-r--r--openstack_dashboard/dashboards/project/networks/ports/tabs.py49
-rw-r--r--openstack_dashboard/dashboards/project/networks/ports/urls.py28
-rw-r--r--openstack_dashboard/dashboards/project/networks/ports/views.py24
-rw-r--r--openstack_dashboard/dashboards/project/networks/subnets/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/project/networks/subnets/forms.py139
-rw-r--r--openstack_dashboard/dashboards/project/networks/subnets/tables.py106
-rw-r--r--openstack_dashboard/dashboards/project/networks/subnets/tabs.py49
-rw-r--r--openstack_dashboard/dashboards/project/networks/subnets/urls.py28
-rw-r--r--openstack_dashboard/dashboards/project/networks/subnets/views.py111
-rw-r--r--openstack_dashboard/dashboards/project/networks/tables.py108
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/_create.html24
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/_detail_overview.html20
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/_network_ips.html10
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/_update.html24
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/create.html11
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/detail.html18
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/index.html11
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/ports/_detail_overview.html41
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/ports/_port_ips.html7
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/ports/detail.html15
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/subnets/_create.html25
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/subnets/_detail_overview.html29
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/subnets/_update.html33
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/subnets/create.html11
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/subnets/detail.html15
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/subnets/index.html11
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/subnets/update.html11
-rw-r--r--openstack_dashboard/dashboards/project/networks/templates/networks/update.html11
-rw-r--r--openstack_dashboard/dashboards/project/networks/tests.py782
-rw-r--r--openstack_dashboard/dashboards/project/networks/urls.py39
-rw-r--r--openstack_dashboard/dashboards/project/networks/views.py143
-rw-r--r--openstack_dashboard/dashboards/project/networks/workflows.py162
-rw-r--r--openstack_dashboard/dashboards/project/overview/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/project/overview/panel.py33
-rw-r--r--openstack_dashboard/dashboards/project/overview/templates/overview/usage.csv11
-rw-r--r--openstack_dashboard/dashboards/project/overview/templates/overview/usage.html13
-rw-r--r--openstack_dashboard/dashboards/project/overview/tests.py144
-rw-r--r--openstack_dashboard/dashboards/project/overview/urls.py30
-rw-r--r--openstack_dashboard/dashboards/project/overview/views.py37
-rw-r--r--openstack_dashboard/dashboards/project/volumes/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/project/volumes/forms.py219
-rw-r--r--openstack_dashboard/dashboards/project/volumes/panel.py30
-rw-r--r--openstack_dashboard/dashboards/project/volumes/tables.py227
-rw-r--r--openstack_dashboard/dashboards/project/volumes/tabs.py49
-rw-r--r--openstack_dashboard/dashboards/project/volumes/templates/volumes/_attach.html25
-rw-r--r--openstack_dashboard/dashboards/project/volumes/templates/volumes/_create.html57
-rw-r--r--openstack_dashboard/dashboards/project/volumes/templates/volumes/_create_snapshot.html25
-rw-r--r--openstack_dashboard/dashboards/project/volumes/templates/volumes/_detail_overview.html49
-rw-r--r--openstack_dashboard/dashboards/project/volumes/templates/volumes/attach.html11
-rw-r--r--openstack_dashboard/dashboards/project/volumes/templates/volumes/create.html11
-rw-r--r--openstack_dashboard/dashboards/project/volumes/templates/volumes/create_snapshot.html11
-rw-r--r--openstack_dashboard/dashboards/project/volumes/templates/volumes/detail.html15
-rw-r--r--openstack_dashboard/dashboards/project/volumes/templates/volumes/index.html11
-rw-r--r--openstack_dashboard/dashboards/project/volumes/tests.py329
-rw-r--r--openstack_dashboard/dashboards/project/volumes/urls.py35
-rw-r--r--openstack_dashboard/dashboards/project/volumes/views.py184
-rw-r--r--openstack_dashboard/dashboards/settings/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/settings/dashboard.py31
-rw-r--r--openstack_dashboard/dashboards/settings/ec2/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/settings/ec2/forms.py110
-rw-r--r--openstack_dashboard/dashboards/settings/ec2/panel.py29
-rw-r--r--openstack_dashboard/dashboards/settings/ec2/templates/ec2/download_form.html25
-rw-r--r--openstack_dashboard/dashboards/settings/ec2/templates/ec2/ec2rc.sh.template15
-rw-r--r--openstack_dashboard/dashboards/settings/ec2/templates/ec2/index.html11
-rw-r--r--openstack_dashboard/dashboards/settings/ec2/tests.py70
-rw-r--r--openstack_dashboard/dashboards/settings/ec2/urls.py23
-rw-r--r--openstack_dashboard/dashboards/settings/ec2/views.py32
-rw-r--r--openstack_dashboard/dashboards/settings/models.py23
-rw-r--r--openstack_dashboard/dashboards/settings/project/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/settings/project/forms.py72
-rw-r--r--openstack_dashboard/dashboards/settings/project/panel.py29
-rw-r--r--openstack_dashboard/dashboards/settings/project/tables.py33
-rw-r--r--openstack_dashboard/dashboards/settings/project/templates/project/_openrc.html32
-rw-r--r--openstack_dashboard/dashboards/settings/project/templates/project/openrc.sh.template24
-rw-r--r--openstack_dashboard/dashboards/settings/project/templates/project/settings.html11
-rw-r--r--openstack_dashboard/dashboards/settings/project/urls.py23
-rw-r--r--openstack_dashboard/dashboards/settings/project/views.py44
-rw-r--r--openstack_dashboard/dashboards/settings/user/__init__.py0
-rw-r--r--openstack_dashboard/dashboards/settings/user/forms.py59
-rw-r--r--openstack_dashboard/dashboards/settings/user/panel.py29
-rw-r--r--openstack_dashboard/dashboards/settings/user/templates/user/_settings.html26
-rw-r--r--openstack_dashboard/dashboards/settings/user/templates/user/settings.html11
-rw-r--r--openstack_dashboard/dashboards/settings/user/urls.py23
-rw-r--r--openstack_dashboard/dashboards/settings/user/views.py31
-rw-r--r--openstack_dashboard/locale/bg_BG/LC_MESSAGES/django.mobin1821 -> 24445 bytes
-rw-r--r--openstack_dashboard/locale/bg_BG/LC_MESSAGES/django.po3252
-rw-r--r--openstack_dashboard/locale/cs/LC_MESSAGES/django.mobin1588 -> 1588 bytes
-rw-r--r--openstack_dashboard/locale/cs/LC_MESSAGES/django.po3242
-rw-r--r--openstack_dashboard/locale/en/LC_MESSAGES/django.mobin1566 -> 36006 bytes
-rw-r--r--openstack_dashboard/locale/en/LC_MESSAGES/django.po3290
-rw-r--r--openstack_dashboard/locale/es/LC_MESSAGES/django.mobin1564 -> 53340 bytes
-rw-r--r--openstack_dashboard/locale/es/LC_MESSAGES/django.po3335
-rw-r--r--openstack_dashboard/locale/fr/LC_MESSAGES/django.mobin1577 -> 1520 bytes
-rw-r--r--openstack_dashboard/locale/fr/LC_MESSAGES/django.po3225
-rw-r--r--openstack_dashboard/locale/it/LC_MESSAGES/django.mobin0 -> 26275 bytes
-rw-r--r--openstack_dashboard/locale/it/LC_MESSAGES/django.po3347
-rw-r--r--openstack_dashboard/locale/ja/LC_MESSAGES/django.mobin1724 -> 60197 bytes
-rw-r--r--openstack_dashboard/locale/ja/LC_MESSAGES/django.po3323
-rw-r--r--openstack_dashboard/locale/ko_KR/LC_MESSAGES/django.mobin1634 -> 2705 bytes
-rw-r--r--openstack_dashboard/locale/ko_KR/LC_MESSAGES/django.po3226
-rw-r--r--openstack_dashboard/locale/nl_NL/LC_MESSAGES/django.mobin1577 -> 9678 bytes
-rw-r--r--openstack_dashboard/locale/nl_NL/LC_MESSAGES/django.po3228
-rw-r--r--openstack_dashboard/locale/pl/LC_MESSAGES/django.mobin478 -> 810 bytes
-rw-r--r--openstack_dashboard/locale/pl/LC_MESSAGES/django.po3463
-rw-r--r--openstack_dashboard/locale/pt/LC_MESSAGES/django.mobin1549 -> 30497 bytes
-rw-r--r--openstack_dashboard/locale/pt/LC_MESSAGES/django.po3288
-rw-r--r--openstack_dashboard/locale/pt_BR/LC_MESSAGES/django.mobin1554 -> 36757 bytes
-rw-r--r--openstack_dashboard/locale/pt_BR/LC_MESSAGES/django.po3276
-rw-r--r--openstack_dashboard/locale/ru/LC_MESSAGES/django.mobin0 -> 494 bytes
-rw-r--r--openstack_dashboard/locale/ru/LC_MESSAGES/django.po3297
-rw-r--r--openstack_dashboard/locale/zh_CN/LC_MESSAGES/django.mobin1468 -> 14112 bytes
-rw-r--r--openstack_dashboard/locale/zh_CN/LC_MESSAGES/django.po3234
-rw-r--r--openstack_dashboard/locale/zh_TW/LC_MESSAGES/django.mobin1516 -> 45327 bytes
-rw-r--r--openstack_dashboard/locale/zh_TW/LC_MESSAGES/django.po3257
-rw-r--r--openstack_dashboard/openstack/__init__.py0
-rw-r--r--openstack_dashboard/openstack/common/__init__.py0
-rw-r--r--openstack_dashboard/openstack/common/setup.py200
-rw-r--r--openstack_dashboard/settings.py9
-rw-r--r--openstack_dashboard/templates/_header.html10
-rw-r--r--openstack_dashboard/test/api_tests/__init__.py0
-rw-r--r--openstack_dashboard/test/api_tests/base_tests.py149
-rw-r--r--openstack_dashboard/test/api_tests/glance_tests.py67
-rw-r--r--openstack_dashboard/test/api_tests/keystone_tests.py98
-rw-r--r--openstack_dashboard/test/api_tests/nova_tests.py206
-rw-r--r--openstack_dashboard/test/api_tests/quantum_tests.py205
-rw-r--r--openstack_dashboard/test/api_tests/swift_tests.py120
-rw-r--r--openstack_dashboard/test/helpers.py298
-rw-r--r--openstack_dashboard/test/settings.py79
-rw-r--r--openstack_dashboard/test/templates/404.html1
-rw-r--r--openstack_dashboard/test/templates/500.html1
-rw-r--r--openstack_dashboard/test/templates/_tab.html1
-rw-r--r--openstack_dashboard/test/templates/base-sidebar.html0
-rw-r--r--openstack_dashboard/test/templates/registration/login.html0
-rw-r--r--openstack_dashboard/test/templates/tab_group.html1
-rw-r--r--openstack_dashboard/test/templates/workflow.html1
-rw-r--r--openstack_dashboard/test/test_data/__init__.py0
-rw-r--r--openstack_dashboard/test/test_data/exceptions.py67
-rw-r--r--openstack_dashboard/test/test_data/glance_data.py89
-rw-r--r--openstack_dashboard/test/test_data/keystone_data.py160
-rw-r--r--openstack_dashboard/test/test_data/nova_data.py343
-rw-r--r--openstack_dashboard/test/test_data/quantum_data.py111
-rw-r--r--openstack_dashboard/test/test_data/swift_data.py39
-rw-r--r--openstack_dashboard/test/test_data/utils.py126
-rw-r--r--openstack_dashboard/test/tests/selenium.py24
-rw-r--r--openstack_dashboard/urls.py5
-rw-r--r--openstack_dashboard/usage/__init__.py19
-rw-r--r--openstack_dashboard/usage/base.py156
-rw-r--r--openstack_dashboard/usage/tables.py71
-rw-r--r--openstack_dashboard/usage/views.py54
-rw-r--r--openstack_dashboard/views.py38
401 files changed, 72652 insertions, 257 deletions
diff --git a/openstack_dashboard/api/__init__.py b/openstack_dashboard/api/__init__.py
new file mode 100644
index 000000000..65383e366
--- /dev/null
+++ b/openstack_dashboard/api/__init__.py
@@ -0,0 +1,39 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.
+
+"""
+Methods and interface objects used to interact with external APIs.
+
+API method calls return objects that are in many cases objects with
+attributes that are direct maps to the data returned from the API http call.
+Unfortunately, these objects are also often constructed dynamically, making
+it difficult to know what data is available from the API object. Because of
+this, all API calls should wrap their returned object in one defined here,
+using only explicitly defined atributes and/or methods.
+
+In other words, Horizon developers not working on openstack_dashboard.api
+shouldn't need to understand the finer details of APIs for
+Keystone/Nova/Glance/Swift et. al.
+"""
+from openstack_dashboard.api.glance import *
+from openstack_dashboard.api.keystone import *
+from openstack_dashboard.api.nova import *
+from openstack_dashboard.api.swift import *
+from openstack_dashboard.api.quantum import *
diff --git a/openstack_dashboard/api/base.py b/openstack_dashboard/api/base.py
new file mode 100644
index 000000000..15f9f9eeb
--- /dev/null
+++ b/openstack_dashboard/api/base.py
@@ -0,0 +1,118 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.conf import settings
+
+from horizon import exceptions
+
+
+__all__ = ('APIResourceWrapper', 'APIDictWrapper',
+ 'get_service_from_catalog', 'url_for',)
+
+
+LOG = logging.getLogger(__name__)
+
+
+class APIResourceWrapper(object):
+ """ Simple wrapper for api objects
+
+ Define _attrs on the child class and pass in the
+ api object as the only argument to the constructor
+ """
+ _attrs = []
+
+ def __init__(self, apiresource):
+ self._apiresource = apiresource
+
+ def __getattr__(self, attr):
+ if attr in self._attrs:
+ # __getattr__ won't find properties
+ return self._apiresource.__getattribute__(attr)
+ else:
+ msg = ('Attempted to access unknown attribute "%s" on '
+ 'APIResource object of type "%s" wrapping resource of '
+ 'type "%s".') % (attr, self.__class__,
+ self._apiresource.__class__)
+ LOG.debug(exceptions.error_color(msg))
+ raise AttributeError(attr)
+
+
+class APIDictWrapper(object):
+ """ Simple wrapper for api dictionaries
+
+ Some api calls return dictionaries. This class provides identical
+ behavior as APIResourceWrapper, except that it will also behave as a
+ dictionary, in addition to attribute accesses.
+
+ Attribute access is the preferred method of access, to be
+ consistent with api resource objects from novclient.
+ """
+ def __init__(self, apidict):
+ self._apidict = apidict
+
+ def __getattr__(self, attr):
+ try:
+ return self._apidict[attr]
+ except KeyError:
+ msg = 'Unknown attribute "%(attr)s" on APIResource object ' \
+ 'of type "%(cls)s"' % {'attr': attr, 'cls': self.__class__}
+ LOG.debug(exceptions.error_color(msg))
+ raise AttributeError(msg)
+
+ def __getitem__(self, item):
+ try:
+ return self.__getattr__(item)
+ except AttributeError, e:
+ # caller is expecting a KeyError
+ raise KeyError(e)
+
+ def get(self, item, default=None):
+ try:
+ return self.__getattr__(item)
+ except AttributeError:
+ return default
+
+
+def get_service_from_catalog(catalog, service_type):
+ if catalog:
+ for service in catalog:
+ if service['type'] == service_type:
+ return service
+ return None
+
+
+def url_for(request, service_type, admin=False, endpoint_type=None):
+ endpoint_type = endpoint_type or getattr(settings,
+ 'OPENSTACK_ENDPOINT_TYPE',
+ 'publicURL')
+ catalog = request.user.service_catalog
+ service = get_service_from_catalog(catalog, service_type)
+ if service:
+ try:
+ if admin:
+ return service['endpoints'][0]['adminURL']
+ else:
+ return service['endpoints'][0][endpoint_type]
+ except (IndexError, KeyError):
+ raise exceptions.ServiceCatalogException(service_type)
+ else:
+ raise exceptions.ServiceCatalogException(service_type)
diff --git a/openstack_dashboard/api/glance.py b/openstack_dashboard/api/glance.py
new file mode 100644
index 000000000..9e0666fad
--- /dev/null
+++ b/openstack_dashboard/api/glance.py
@@ -0,0 +1,98 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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
+
+import logging
+import thread
+import urlparse
+
+from django.conf import settings
+
+import glanceclient as glance_client
+
+from openstack_dashboard.api.base import url_for
+
+
+LOG = logging.getLogger(__name__)
+
+
+def glanceclient(request):
+ o = urlparse.urlparse(url_for(request, 'image'))
+ url = "://".join((o.scheme, o.netloc))
+ insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
+ LOG.debug('glanceclient connection created using token "%s" and url "%s"'
+ % (request.user.token.id, url))
+ return glance_client.Client('1', url, token=request.user.token.id,
+ insecure=insecure)
+
+
+def image_delete(request, image_id):
+ return glanceclient(request).images.delete(image_id)
+
+
+def image_get(request, image_id):
+ """
+ Returns an Image object populated with metadata for image
+ with supplied identifier.
+ """
+ return glanceclient(request).images.get(image_id)
+
+
+def image_list_detailed(request, marker=None, filters=None):
+ limit = getattr(settings, 'API_RESULT_LIMIT', 1000)
+ page_size = getattr(settings, 'API_RESULT_PAGE_SIZE', 20)
+ kwargs = {'filters': filters or {}}
+ if marker:
+ kwargs['marker'] = marker
+ images = list(glanceclient(request).images.list(page_size=page_size,
+ limit=limit,
+ **kwargs))
+ # Glance returns (page_size + 1) items if more items are available
+ if(len(images) > page_size):
+ return (images[0:-1], True)
+ else:
+ return (images, False)
+
+
+def image_update(request, image_id, **kwargs):
+ return glanceclient(request).images.update(image_id, **kwargs)
+
+
+def image_create(request, **kwargs):
+ copy_from = None
+
+ if kwargs.get('copy_from'):
+ copy_from = kwargs.pop('copy_from')
+
+ image = glanceclient(request).images.create(**kwargs)
+
+ if copy_from:
+ thread.start_new_thread(image_update,
+ (request, image.id),
+ {'copy_from': copy_from})
+
+ return image
+
+
+def snapshot_list_detailed(request, marker=None, extra_filters=None):
+ filters = {'property-image_type': 'snapshot'}
+ filters.update(extra_filters or {})
+ return image_list_detailed(request, marker, filters)
diff --git a/openstack_dashboard/api/keystone.py b/openstack_dashboard/api/keystone.py
new file mode 100644
index 000000000..aabf5006e
--- /dev/null
+++ b/openstack_dashboard/api/keystone.py
@@ -0,0 +1,291 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Openstack, LLC
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+import urlparse
+
+from django.conf import settings
+from django.utils.translation import ugettext_lazy as _
+
+from keystoneclient import service_catalog
+from keystoneclient.v2_0 import client as keystone_client
+from keystoneclient.v2_0 import tokens
+
+from openstack_auth.backend import KEYSTONE_CLIENT_ATTR
+
+from horizon import exceptions
+
+from openstack_dashboard.api import base
+
+
+LOG = logging.getLogger(__name__)
+DEFAULT_ROLE = None
+
+
+class Service(base.APIDictWrapper):
+ """ Wrapper for a dict based on the service data from keystone. """
+ _attrs = ['id', 'type', 'name']
+
+ def __init__(self, service, *args, **kwargs):
+ super(Service, self).__init__(service, *args, **kwargs)
+ self.url = service['endpoints'][0]['internalURL']
+ self.host = urlparse.urlparse(self.url).hostname
+ self.region = service['endpoints'][0]['region']
+ self.disabled = None
+
+ def __unicode__(self):
+ if(self.type == "identity"):
+ return _("%(type)s (%(backend)s backend)") \
+ % {"type": self.type,
+ "backend": keystone_backend_name()}
+ else:
+ return self.type
+
+ def __repr__(self):
+ return "<Service: %s>" % unicode(self)
+
+
+def _get_endpoint_url(request, endpoint_type, catalog=None):
+ if getattr(request.user, "service_catalog", None):
+ return base.url_for(request,
+ service_type='identity',
+ endpoint_type=endpoint_type)
+ return request.session.get('region_endpoint',
+ getattr(settings, 'OPENSTACK_KEYSTONE_URL'))
+
+
+def keystoneclient(request, admin=False):
+ """Returns a client connected to the Keystone backend.
+
+ Several forms of authentication are supported:
+
+ * Username + password -> Unscoped authentication
+ * Username + password + tenant id -> Scoped authentication
+ * Unscoped token -> Unscoped authentication
+ * Unscoped token + tenant id -> Scoped authentication
+ * Scoped token -> Scoped authentication
+
+ Available services and data from the backend will vary depending on
+ whether the authentication was scoped or unscoped.
+
+ Lazy authentication if an ``endpoint`` parameter is provided.
+
+ Calls requiring the admin endpoint should have ``admin=True`` passed in
+ as a keyword argument.
+
+ The client is cached so that subsequent API calls during the same
+ request/response cycle don't have to be re-authenticated.
+ """
+ user = request.user
+ if admin:
+ if not user.is_superuser:
+ raise exceptions.NotAuthorized
+ endpoint_type = 'adminURL'
+ else:
+ endpoint_type = getattr(settings,
+ 'OPENSTACK_ENDPOINT_TYPE',
+ 'internalURL')
+
+ # Take care of client connection caching/fetching a new client.
+ # Admin vs. non-admin clients are cached separately for token matching.
+ cache_attr = "_keystoneclient_admin" if admin else KEYSTONE_CLIENT_ATTR
+ if hasattr(request, cache_attr) and (not user.token.id
+ or getattr(request, cache_attr).auth_token == user.token.id):
+ LOG.debug("Using cached client for token: %s" % user.token.id)
+ conn = getattr(request, cache_attr)
+ else:
+ endpoint = _get_endpoint_url(request, endpoint_type)
+ # FIXME(ttrifonov): temporarily commented,
+ # as the fix in Keystone is not merged yet
+ #insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
+ LOG.debug("Creating a new keystoneclient connection to %s." % endpoint)
+ conn = keystone_client.Client(token=user.token.id,
+ endpoint=endpoint)
+ # insecure=insecure)
+ setattr(request, cache_attr, conn)
+ return conn
+
+
+def tenant_create(request, tenant_name, description, enabled):
+ return keystoneclient(request, admin=True).tenants.create(tenant_name,
+ description,
+ enabled)
+
+
+def tenant_get(request, tenant_id, admin=False):
+ return keystoneclient(request, admin=admin).tenants.get(tenant_id)
+
+
+def tenant_delete(request, tenant_id):
+ keystoneclient(request, admin=True).tenants.delete(tenant_id)
+
+
+def tenant_list(request, admin=False):
+ return keystoneclient(request, admin=admin).tenants.list()
+
+
+def tenant_update(request, tenant_id, tenant_name, description, enabled):
+ return keystoneclient(request, admin=True).tenants.update(tenant_id,
+ tenant_name,
+ description,
+ enabled)
+
+
+def token_create_scoped(request, tenant, token):
+ '''
+ Creates a scoped token using the tenant id and unscoped token; retrieves
+ the service catalog for the given tenant.
+ '''
+ if hasattr(request, '_keystone'):
+ del request._keystone
+ c = keystoneclient(request)
+ raw_token = c.tokens.authenticate(tenant_id=tenant,
+ token=token,
+ return_raw=True)
+ c.service_catalog = service_catalog.ServiceCatalog(raw_token)
+ if request.user.is_superuser:
+ c.management_url = c.service_catalog.url_for(service_type='identity',
+ endpoint_type='adminURL')
+ else:
+ endpoint_type = getattr(settings,
+ 'OPENSTACK_ENDPOINT_TYPE',
+ 'internalURL')
+ c.management_url = c.service_catalog.url_for(
+ service_type='identity', endpoint_type=endpoint_type)
+ scoped_token = tokens.Token(tokens.TokenManager, raw_token)
+ return scoped_token
+
+
+def user_list(request, tenant_id=None):
+ return keystoneclient(request, admin=True).users.list(tenant_id=tenant_id)
+
+
+def user_create(request, user_id, email, password, tenant_id, enabled):
+ return keystoneclient(request, admin=True).users.create(user_id,
+ password,
+ email,
+ tenant_id,
+ enabled)
+
+
+def user_delete(request, user_id):
+ keystoneclient(request, admin=True).users.delete(user_id)
+
+
+def user_get(request, user_id, admin=True):
+ return keystoneclient(request, admin=admin).users.get(user_id)
+
+
+def user_update(request, user, **data):
+ return keystoneclient(request, admin=True).users.update(user, **data)
+
+
+def user_update_enabled(request, user_id, enabled):
+ return keystoneclient(request, admin=True).users.update_enabled(user_id,
+ enabled)
+
+
+def user_update_password(request, user_id, password, admin=True):
+ return keystoneclient(request, admin=admin).users.update_password(user_id,
+ password)
+
+
+def user_update_tenant(request, user_id, tenant_id, admin=True):
+ return keystoneclient(request, admin=admin).users.update_tenant(user_id,
+ tenant_id)
+
+
+def role_list(request):
+ """ Returns a global list of available roles. """
+ return keystoneclient(request, admin=True).roles.list()
+
+
+def roles_for_user(request, user, project):
+ return keystoneclient(request, admin=True).roles.roles_for_user(user,
+ project)
+
+
+def add_tenant_user_role(request, tenant_id, user_id, role_id):
+ """ Adds a role for a user on a tenant. """
+ return keystoneclient(request, admin=True).roles.add_user_role(user_id,
+ role_id,
+ tenant_id)
+
+
+def remove_tenant_user_role(request, tenant_id, user_id, role_id):
+ """ Removes a given single role for a user from a tenant. """
+ client = keystoneclient(request, admin=True)
+ client.roles.remove_user_role(user_id, role_id, tenant_id)
+
+
+def remove_tenant_user(request, tenant_id, user_id):
+ """ Removes all roles from a user on a tenant, removing them from it. """
+ client = keystoneclient(request, admin=True)
+ roles = client.roles.roles_for_user(user_id, tenant_id)
+ for role in roles:
+ client.roles.remove_user_role(user_id, role.id, tenant_id)
+
+
+def get_default_role(request):
+ """
+ Gets the default role object from Keystone and saves it as a global
+ since this is configured in settings and should not change from request
+ to request. Supports lookup by name or id.
+ """
+ global DEFAULT_ROLE
+ default = getattr(settings, "OPENSTACK_KEYSTONE_DEFAULT_ROLE", None)
+ if default and DEFAULT_ROLE is None:
+ try:
+ roles = keystoneclient(request, admin=True).roles.list()
+ except:
+ roles = []
+ exceptions.handle(request)
+ for role in roles:
+ if role.id == default or role.name == default:
+ DEFAULT_ROLE = role
+ break
+ return DEFAULT_ROLE
+
+
+def list_ec2_credentials(request, user_id):
+ return keystoneclient(request).ec2.list(user_id)
+
+
+def create_ec2_credentials(request, user_id, tenant_id):
+ return keystoneclient(request).ec2.create(user_id, tenant_id)
+
+
+def get_user_ec2_credentials(request, user_id, access_token):
+ return keystoneclient(request).ec2.get(user_id, access_token)
+
+
+def keystone_can_edit_user():
+ if hasattr(settings, "OPENSTACK_KEYSTONE_BACKEND"):
+ return settings.OPENSTACK_KEYSTONE_BACKEND['can_edit_user']
+ else:
+ return False
+
+
+def keystone_backend_name():
+ if hasattr(settings, "OPENSTACK_KEYSTONE_BACKEND"):
+ return settings.OPENSTACK_KEYSTONE_BACKEND['name']
+ else:
+ return 'unknown'
diff --git a/openstack_dashboard/api/nova.py b/openstack_dashboard/api/nova.py
new file mode 100644
index 000000000..088231470
--- /dev/null
+++ b/openstack_dashboard/api/nova.py
@@ -0,0 +1,587 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Openstack, LLC
+# Copyright 2012 Nebula, Inc.
+# Copyright (c) 2012 X.commerce, a business unit of eBay Inc.
+#
+# 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
+
+import logging
+
+from django.conf import settings
+from django.utils.translation import ugettext as _
+
+from cinderclient.v1 import client as cinder_client
+
+from novaclient.v1_1 import client as nova_client
+from novaclient.v1_1 import security_group_rules as nova_rules
+from novaclient.v1_1.security_groups import SecurityGroup as NovaSecurityGroup
+from novaclient.v1_1.servers import REBOOT_HARD
+
+from horizon import exceptions
+from horizon.utils.memoized import memoized
+
+from openstack_dashboard.api.base import (APIResourceWrapper,
+ APIDictWrapper, url_for)
+
+
+LOG = logging.getLogger(__name__)
+
+
+# API static values
+INSTANCE_ACTIVE_STATE = 'ACTIVE'
+VOLUME_STATE_AVAILABLE = "available"
+
+
+class VNCConsole(APIDictWrapper):
+ """Wrapper for the "console" dictionary returned by the
+ novaclient.servers.get_vnc_console method.
+ """
+ _attrs = ['url', 'type']
+
+
+class Quota(object):
+ """Wrapper for individual limits in a quota."""
+ def __init__(self, name, limit):
+ self.name = name
+ self.limit = limit
+
+ def __repr__(self):
+ return "<Quota: (%s, %s)>" % (self.name, self.limit)
+
+
+class QuotaSet(object):
+ """Wrapper for novaclient.quotas.QuotaSet objects which wraps the
+ individual quotas inside Quota objects.
+ """
+ def __init__(self, apiresource):
+ self.items = []
+ for k in apiresource._info.keys():
+ if k in ['id']:
+ continue
+ limit = apiresource._info[k]
+ v = int(limit) if limit is not None else limit
+ q = Quota(k, v)
+ self.items.append(q)
+ setattr(self, k, v)
+
+
+class Server(APIResourceWrapper):
+ """Simple wrapper around novaclient.server.Server
+
+ Preserves the request info so image name can later be retrieved
+
+ """
+ _attrs = ['addresses', 'attrs', 'id', 'image', 'links',
+ 'metadata', 'name', 'private_ip', 'public_ip', 'status', 'uuid',
+ 'image_name', 'VirtualInterfaces', 'flavor', 'key_name',
+ 'tenant_id', 'user_id', 'OS-EXT-STS:power_state',
+ 'OS-EXT-STS:task_state', 'OS-EXT-SRV-ATTR:instance_name',
+ 'OS-EXT-SRV-ATTR:host']
+
+ def __init__(self, apiresource, request):
+ super(Server, self).__init__(apiresource)
+ self.request = request
+
+ @property
+ def image_name(self):
+ import glanceclient.exc as glance_exceptions
+ from openstack_dashboard.api import glance
+ try:
+ image = glance.image_get(self.request, self.image['id'])
+ return image.name
+ except glance_exceptions.ClientException:
+ return "(not found)"
+
+ @property
+ def internal_name(self):
+ return getattr(self, 'OS-EXT-SRV-ATTR:instance_name', "")
+
+ def reboot(self, hardness=REBOOT_HARD):
+ novaclient(self.request).servers.reboot(self.id, hardness)
+
+
+class Usage(APIResourceWrapper):
+ """Simple wrapper around contrib/simple_usage.py."""
+ _attrs = ['start', 'server_usages', 'stop', 'tenant_id',
+ 'total_local_gb_usage', 'total_memory_mb_usage',
+ 'total_vcpus_usage', 'total_hours']
+
+ def get_summary(self):
+ return {'instances': self.total_active_instances,
+ 'memory_mb': self.memory_mb,
+ 'vcpus': getattr(self, "total_vcpus_usage", 0),
+ 'vcpu_hours': self.vcpu_hours,
+ 'local_gb': self.local_gb,
+ 'disk_gb_hours': self.disk_gb_hours}
+
+ @property
+ def total_active_instances(self):
+ return sum(1 for s in self.server_usages if s['ended_at'] is None)
+
+ @property
+ def vcpus(self):
+ return sum(s['vcpus'] for s in self.server_usages
+ if s['ended_at'] is None)
+
+ @property
+ def vcpu_hours(self):
+ return getattr(self, "total_hours", 0)
+
+ @property
+ def local_gb(self):
+ return sum(s['local_gb'] for s in self.server_usages
+ if s['ended_at'] is None)
+
+ @property
+ def memory_mb(self):
+ return sum(s['memory_mb'] for s in self.server_usages
+ if s['ended_at'] is None)
+
+ @property
+ def disk_gb_hours(self):
+ return getattr(self, "total_local_gb_usage", 0)
+
+
+class SecurityGroup(APIResourceWrapper):
+ """Wrapper around novaclient.security_groups.SecurityGroup which wraps its
+ rules in SecurityGroupRule objects and allows access to them.
+ """
+ _attrs = ['id', 'name', 'description', 'tenant_id']
+
+ @property
+ def rules(self):
+ """Wraps transmitted rule info in the novaclient rule class."""
+ if "_rules" not in self.__dict__:
+ manager = nova_rules.SecurityGroupRuleManager
+ self._rules = [nova_rules.SecurityGroupRule(manager, rule)
+ for rule in self._apiresource.rules]
+ return self.__dict__['_rules']
+
+ @rules.setter
+ def rules(self, value):
+ self._rules = value
+
+
+class SecurityGroupRule(APIResourceWrapper):
+ """ Wrapper for individual rules in a SecurityGroup. """
+ _attrs = ['id', 'ip_protocol', 'from_port', 'to_port', 'ip_range', 'group']
+
+ def __unicode__(self):
+ if 'name' in self.group:
+ vals = {'from': self.from_port,
+ 'to': self.to_port,
+ 'group': self.group['name']}
+ return _('ALLOW %(from)s:%(to)s from %(group)s') % vals
+ else:
+ vals = {'from': self.from_port,
+ 'to': self.to_port,
+ 'cidr': self.ip_range['cidr']}
+ return _('ALLOW %(from)s:%(to)s from %(cidr)s') % vals
+
+
+def novaclient(request):
+ insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
+ LOG.debug('novaclient connection created using token "%s" and url "%s"' %
+ (request.user.token.id, url_for(request, 'compute')))
+ c = nova_client.Client(request.user.username,
+ request.user.token.id,
+ project_id=request.user.tenant_id,
+ auth_url=url_for(request, 'compute'),
+ insecure=insecure)
+ c.client.auth_token = request.user.token.id
+ c.client.management_url = url_for(request, 'compute')
+ return c
+
+
+def cinderclient(request):
+ insecure = getattr(settings, 'OPENSTACK_SSL_NO_VERIFY', False)
+ LOG.debug('cinderclient connection created using token "%s" and url "%s"' %
+ (request.user.token.id, url_for(request, 'volume')))
+ c = cinder_client.Client(request.user.username,
+ request.user.token.id,
+ project_id=request.user.tenant_id,
+ auth_url=url_for(request, 'volume'),
+ insecure=insecure)
+ c.client.auth_token = request.user.token.id
+ c.client.management_url = url_for(request, 'volume')
+ return c
+
+
+def server_vnc_console(request, instance_id, console_type='novnc'):
+ return VNCConsole(novaclient(request).servers.get_vnc_console(instance_id,
+ console_type)['console'])
+
+
+def flavor_create(request, name, memory, vcpu, disk, flavor_id, ephemeral=0):
+ return novaclient(request).flavors.create(name, int(memory), int(vcpu),
+ int(disk), flavor_id,
+ ephemeral=int(ephemeral))
+
+
+def flavor_delete(request, flavor_id):
+ novaclient(request).flavors.delete(flavor_id)
+
+
+def flavor_get(request, flavor_id):
+ return novaclient(request).flavors.get(flavor_id)
+
+
+@memoized
+def flavor_list(request):
+ """Get the list of available instance sizes (flavors)."""
+ return novaclient(request).flavors.list()
+
+
+def tenant_floating_ip_list(request):
+ """Fetches a list of all floating ips."""
+ return novaclient(request).floating_ips.list()
+
+
+def floating_ip_pools_list(request):
+ """Fetches a list of all floating ip pools."""
+ return novaclient(request).floating_ip_pools.list()
+
+
+def tenant_floating_ip_get(request, floating_ip_id):
+ """Fetches a floating ip."""
+ return novaclient(request).floating_ips.get(floating_ip_id)
+
+
+def tenant_floating_ip_allocate(request, pool=None):
+ """Allocates a floating ip to tenant. Optionally you may provide a pool
+ for which you would like the IP.
+ """
+ return novaclient(request).floating_ips.create(pool=pool)
+
+
+def tenant_floating_ip_release(request, floating_ip_id):
+ """Releases floating ip from the pool of a tenant."""
+ return novaclient(request).floating_ips.delete(floating_ip_id)
+
+
+def snapshot_create(request, instance_id, name):
+ return novaclient(request).servers.create_image(instance_id, name)
+
+
+def keypair_create(request, name):
+ return novaclient(request).keypairs.create(name)
+
+
+def keypair_import(request, name, public_key):
+ return novaclient(request).keypairs.create(name, public_key)
+
+
+def keypair_delete(request, keypair_id):
+ novaclient(request).keypairs.delete(keypair_id)
+
+
+def keypair_list(request):
+ return novaclient(request).keypairs.list()
+
+
+def server_create(request, name, image, flavor, key_name, user_data,
+ security_groups, block_device_mapping, nics=None,
+ instance_count=1):
+ return Server(novaclient(request).servers.create(
+ name, image, flavor, userdata=user_data,
+ security_groups=security_groups,
+ key_name=key_name, block_device_mapping=block_device_mapping,
+ nics=nics,
+ min_count=instance_count), request)
+
+
+def server_delete(request, instance):
+ novaclient(request).servers.delete(instance)
+
+
+def server_get(request, instance_id):
+ return Server(novaclient(request).servers.get(instance_id), request)
+
+
+def server_list(request, search_opts=None, all_tenants=False):
+ if search_opts is None:
+ search_opts = {}
+ if all_tenants:
+ search_opts['all_tenants'] = True
+ else:
+ search_opts['project_id'] = request.user.tenant_id
+ return [Server(s, request)
+ for s in novaclient(request).servers.list(True, search_opts)]
+
+
+def server_console_output(request, instance_id, tail_length=None):
+ """Gets console output of an instance."""
+ return novaclient(request).servers.get_console_output(instance_id,
+ length=tail_length)
+
+
+def server_security_groups(request, instance_id):
+ """Gets security groups of an instance."""
+ # TODO(gabriel): This needs to be moved up to novaclient, and should
+ # be removed once novaclient supports this call.
+ security_groups = []
+ nclient = novaclient(request)
+ resp, body = nclient.client.get('/servers/%s/os-security-groups'
+ % instance_id)
+ if body:
+ # Wrap data in SG objects as novaclient would.
+ sg_objs = [NovaSecurityGroup(nclient.security_groups, sg, loaded=True)
+ for sg in body.get('security_groups', [])]
+ # Then wrap novaclient's object with our own. Yes, sadly wrapping
+ # with two layers of objects is necessary.
+ security_groups = [SecurityGroup(sg) for sg in sg_objs]
+ # Package up the rules, as well.
+ for sg in security_groups:
+ rule_objects = [SecurityGroupRule(rule) for rule in sg.rules]
+ sg.rules = rule_objects
+ return security_groups
+
+
+def server_pause(request, instance_id):
+ novaclient(request).servers.pause(instance_id)
+
+
+def server_unpause(request, instance_id):
+ novaclient(request).servers.unpause(instance_id)
+
+
+def server_suspend(request, instance_id):
+ novaclient(request).servers.suspend(instance_id)
+
+
+def server_resume(request, instance_id):
+ novaclient(request).servers.resume(instance_id)
+
+
+def server_reboot(request, instance_id, hardness=REBOOT_HARD):
+ server = server_get(request, instance_id)
+ server.reboot(hardness)
+
+
+def server_update(request, instance_id, name):
+ response = novaclient(request).servers.update(instance_id, name=name)
+ # TODO(gabriel): servers.update method doesn't return anything. :-(
+ if response is None:
+ return True
+ else:
+ return response
+
+
+def server_add_floating_ip(request, server, floating_ip):
+ """Associates floating IP to server's fixed IP.
+ """
+ server = novaclient(request).servers.get(server)
+ fip = novaclient(request).floating_ips.get(floating_ip)
+ return novaclient(request).servers.add_floating_ip(server.id, fip.ip)
+
+
+def server_remove_floating_ip(request, server, floating_ip):
+ """Removes relationship between floating and server's fixed ip.
+ """
+ fip = novaclient(request).floating_ips.get(floating_ip)
+ server = novaclient(request).servers.get(fip.instance_id)
+ return novaclient(request).servers.remove_floating_ip(server.id, fip.ip)
+
+
+def tenant_quota_get(request, tenant_id):
+ return QuotaSet(novaclient(request).quotas.get(tenant_id))
+
+
+def tenant_quota_update(request, tenant_id, **kwargs):
+ novaclient(request).quotas.update(tenant_id, **kwargs)
+
+
+def tenant_quota_defaults(request, tenant_id):
+ return QuotaSet(novaclient(request).quotas.defaults(tenant_id))
+
+
+def usage_get(request, tenant_id, start, end):
+ return Usage(novaclient(request).usage.get(tenant_id, start, end))
+
+
+def usage_list(request, start, end):
+ return [Usage(u) for u in novaclient(request).usage.list(start, end, True)]
+
+
+@memoized
+def tenant_quota_usages(request):
+ """
+ Builds a dictionary of current usage against quota for the current
+ project.
+ """
+ instances = server_list(request)
+ floating_ips = tenant_floating_ip_list(request)
+ quotas = tenant_quota_get(request, request.user.tenant_id)
+ flavors = dict([(f.id, f) for f in flavor_list(request)])
+ volumes = volume_list(request)
+
+ usages = {'instances': {'flavor_fields': [], 'used': len(instances)},
+ 'cores': {'flavor_fields': ['vcpus'], 'used': 0},
+ 'gigabytes': {'used': sum([int(v.size) for v in volumes]),
+ 'flavor_fields': []},
+ 'volumes': {'used': len(volumes), 'flavor_fields': []},
+ 'ram': {'flavor_fields': ['ram'], 'used': 0},
+ 'floating_ips': {'flavor_fields': [], 'used': len(floating_ips)}}
+
+ for usage in usages:
+ for instance in instances:
+ used_flavor = instance.flavor['id']
+ if used_flavor not in flavors:
+ try:
+ flavors[used_flavor] = flavor_get(request, used_flavor)
+ except:
+ flavors[used_flavor] = {}
+ exceptions.handle(request, ignore=True)
+ for flavor_field in usages[usage]['flavor_fields']:
+ instance_flavor = flavors[used_flavor]
+ usages[usage]['used'] += getattr(instance_flavor,
+ flavor_field,
+ 0)
+
+ usages[usage]['quota'] = getattr(quotas, usage)
+
+ if usages[usage]['quota'] is None:
+ usages[usage]['quota'] = float("inf")
+ usages[usage]['available'] = float("inf")
+ elif type(usages[usage]['quota']) is str:
+ usages[usage]['quota'] = int(usages[usage]['quota'])
+ else:
+ if type(usages[usage]['used']) is str:
+ usages[usage]['used'] = int(usages[usage]['used'])
+
+ usages[usage]['available'] = usages[usage]['quota'] - \
+ usages[usage]['used']
+
+ return usages
+
+
+def security_group_list(request):
+ return [SecurityGroup(g) for g
+ in novaclient(request).security_groups.list()]
+
+
+def security_group_get(request, sg_id):
+ return SecurityGroup(novaclient(request).security_groups.get(sg_id))
+
+
+def security_group_create(request, name, desc):
+ return SecurityGroup(novaclient(request).security_groups.create(name,
+ desc))
+
+
+def security_group_delete(request, security_group_id):
+ novaclient(request).security_groups.delete(security_group_id)
+
+
+def security_group_rule_create(request, parent_group_id, ip_protocol=None,
+ from_port=None, to_port=None, cidr=None,
+ group_id=None):
+ sg = novaclient(request).security_group_rules.create(parent_group_id,
+ ip_protocol,
+ from_port,
+ to_port,
+ cidr,
+ group_id)
+ return SecurityGroupRule(sg)
+
+
+def security_group_rule_delete(request, security_group_rule_id):
+ novaclient(request).security_group_rules.delete(security_group_rule_id)
+
+
+def virtual_interfaces_list(request, instance_id):
+ return novaclient(request).virtual_interfaces.list(instance_id)
+
+
+def volume_list(request, search_opts=None):
+ """
+ To see all volumes in the cloud as an admin you can pass in a special
+ search option: {'all_tenants': 1}
+ """
+ return cinderclient(request).volumes.list(search_opts=search_opts)
+
+
+def volume_get(request, volume_id):
+ volume_data = cinderclient(request).volumes.get(volume_id)
+
+ for attachment in volume_data.attachments:
+ if "server_id" in attachment:
+ instance = server_get(request, attachment['server_id'])
+ attachment['instance_name'] = instance.name
+ else:
+ # Nova volume can occasionally send back error'd attachments
+ # the lack a server_id property; to work around that we'll
+ # give the attached instance a generic name.
+ attachment['instance_name'] = _("Unknown instance")
+ return volume_data
+
+
+def volume_instance_list(request, instance_id):
+ volumes = novaclient(request).volumes.get_server_volumes(instance_id)
+
+ for volume in volumes:
+ volume_data = cinderclient(request).volumes.get(volume.id)
+ volume.name = volume_data.display_name
+
+ return volumes
+
+
+def volume_create(request, size, name, description, snapshot_id=None):
+ return cinderclient(request).volumes.create(size, display_name=name,
+ display_description=description, snapshot_id=snapshot_id)
+
+
+def volume_delete(request, volume_id):
+ cinderclient(request).volumes.delete(volume_id)
+
+
+def volume_attach(request, volume_id, instance_id, device):
+ return novaclient(request).volumes.create_server_volume(instance_id,
+ volume_id,
+ device)
+
+
+def volume_detach(request, instance_id, att_id):
+ novaclient(request).volumes.delete_server_volume(instance_id, att_id)
+
+
+def volume_snapshot_get(request, snapshot_id):
+ return cinderclient(request).volume_snapshots.get(snapshot_id)
+
+
+def volume_snapshot_list(request):
+ return cinderclient(request).volume_snapshots.list()
+
+
+def volume_snapshot_create(request, volume_id, name, description):
+ return cinderclient(request).volume_snapshots.create(
+ volume_id, display_name=name, display_description=description)
+
+
+def volume_snapshot_delete(request, snapshot_id):
+ cinderclient(request).volume_snapshots.delete(snapshot_id)
+
+
+def get_x509_credentials(request):
+ return novaclient(request).certs.create()
+
+
+def get_x509_root_certificate(request):
+ return novaclient(request).certs.get()
diff --git a/openstack_dashboard/api/quantum.py b/openstack_dashboard/api/quantum.py
new file mode 100644
index 000000000..22c86271b
--- /dev/null
+++ b/openstack_dashboard/api/quantum.py
@@ -0,0 +1,261 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Cisco Systems, Inc.
+# Copyright 2012 NEC Corporation
+#
+# 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
+
+import logging
+
+from quantumclient.v2_0 import client as quantum_client
+from django.utils.datastructures import SortedDict
+
+from openstack_dashboard.api.base import APIDictWrapper, url_for
+
+
+LOG = logging.getLogger(__name__)
+
+
+class QuantumAPIDictWrapper(APIDictWrapper):
+
+ def set_id_as_name_if_empty(self, length=8):
+ try:
+ if not self._apidict['name']:
+ id = self._apidict['id']
+ if length:
+ id = id[:length]
+ self._apidict['name'] = '(%s)' % id
+ except KeyError:
+ pass
+
+ def items(self):
+ return self._apidict.items()
+
+
+class Network(QuantumAPIDictWrapper):
+ """Wrapper for quantum Networks"""
+ _attrs = ['name', 'id', 'subnets', 'tenant_id', 'status',
+ 'admin_state_up', 'shared']
+
+ def __init__(self, apiresource):
+ apiresource['admin_state'] = \
+ 'UP' if apiresource['admin_state_up'] else 'DOWN'
+ super(Network, self).__init__(apiresource)
+
+
+class Subnet(QuantumAPIDictWrapper):
+ """Wrapper for quantum subnets"""
+ _attrs = ['name', 'id', 'cidr', 'network_id', 'tenant_id',
+ 'ip_version', 'ipver_str']
+
+ def __init__(self, apiresource):
+ apiresource['ipver_str'] = get_ipver_str(apiresource['ip_version'])
+ super(Subnet, self).__init__(apiresource)
+
+
+class Port(QuantumAPIDictWrapper):
+ """Wrapper for quantum ports"""
+ _attrs = ['name', 'id', 'network_id', 'tenant_id',
+ 'admin_state_up', 'status', 'mac_address',
+ 'fixed_ips', 'host_routes', 'device_id']
+
+ def __init__(self, apiresource):
+ apiresource['admin_state'] = \
+ 'UP' if apiresource['admin_state_up'] else 'DOWN'
+ super(Port, self).__init__(apiresource)
+
+
+IP_VERSION_DICT = {4: 'IPv4', 6: 'IPv6'}
+
+
+def get_ipver_str(ip_version):
+ """Convert an ip version number to a human-friendly string"""
+ return IP_VERSION_DICT.get(ip_version, '')
+
+
+def quantumclient(request):
+ LOG.debug('quantumclient connection created using token "%s" and url "%s"'
+ % (request.user.token.id, url_for(request, 'network')))
+ LOG.debug('user_id=%(user)s, tenant_id=%(tenant)s' %
+ {'user': request.user.id, 'tenant': request.user.tenant_id})
+ c = quantum_client.Client(token=request.user.token.id,
+ endpoint_url=url_for(request, 'network'))
+ return c
+
+
+def network_list(request, **params):
+ LOG.debug("network_list(): params=%s" % (params))
+ networks = quantumclient(request).list_networks(**params).get('networks')
+ # Get subnet list to expand subnet info in network list.
+ subnets = subnet_list(request)
+ subnet_dict = SortedDict([(s['id'], s) for s in subnets])
+ # Expand subnet list from subnet_id to values.
+ for n in networks:
+ n['subnets'] = [subnet_dict[s] for s in n['subnets']]
+ return [Network(n) for n in networks]
+
+
+def network_list_for_tenant(request, tenant_id, **params):
+ """Return a network list available for the tenant.
+ The list contains networks owned by the tenant and public networks.
+ If requested_networks specified, it searches requested_networks only.
+ """
+ LOG.debug("network_list_for_tenant(): tenant_id=%s, params=%s"
+ % (tenant_id, params))
+
+ # If a user has admin role, network list returned by Quantum API
+ # contains networks that do not belong to that tenant.
+ # So we need to specify tenant_id when calling network_list().
+ networks = network_list(request, tenant_id=tenant_id,
+ shared=False, **params)
+
+ # In the current Quantum API, there is no way to retrieve
+ # both owner networks and public networks in a single API call.
+ networks += network_list(request, shared=True, **params)
+
+ return networks
+
+
+def network_get(request, network_id, **params):
+ LOG.debug("network_get(): netid=%s, params=%s" % (network_id, params))
+ network = quantumclient(request).show_network(network_id,
+ **params).get('network')
+ # Since the number of subnets per network must be small,
+ # call subnet_get() for each subnet instead of calling
+ # subnet_list() once.
+ network['subnets'] = [subnet_get(request, sid)
+ for sid in network['subnets']]
+ return Network(network)
+
+
+def network_create(request, **kwargs):
+ """
+ Create a subnet on a specified network.
+ :param request: request context
+ :param tenant_id: (optional) tenant id of the network created
+ :param name: (optional) name of the network created
+ :returns: Subnet object
+ """
+ LOG.debug("network_create(): kwargs = %s" % kwargs)
+ body = {'network': kwargs}
+ network = quantumclient(request).create_network(body=body).get('network')
+ return Network(network)
+
+
+def network_modify(request, network_id, **kwargs):
+ LOG.debug("network_modify(): netid=%s, params=%s" % (network_id, kwargs))
+ body = {'network': kwargs}
+ network = quantumclient(request).update_network(network_id,
+ body=body).get('network')
+ return Network(network)
+
+
+def network_delete(request, network_id):
+ LOG.debug("network_delete(): netid=%s" % network_id)
+ quantumclient(request).delete_network(network_id)
+
+
+def subnet_list(request, **params):
+ LOG.debug("subnet_list(): params=%s" % (params))
+ subnets = quantumclient(request).list_subnets(**params).get('subnets')
+ return [Subnet(s) for s in subnets]
+
+
+def subnet_get(request, subnet_id, **params):
+ LOG.debug("subnet_get(): subnetid=%s, params=%s" % (subnet_id, params))
+ subnet = quantumclient(request).show_subnet(subnet_id,
+ **params).get('subnet')
+ return Subnet(subnet)
+
+
+def subnet_create(request, network_id, cidr, ip_version, **kwargs):
+ """
+ Create a subnet on a specified network.
+ :param request: request context
+ :param network_id: network id a subnet is created on
+ :param cidr: subnet IP address range
+ :param ip_version: IP version (4 or 6)
+ :param gateway_ip: (optional) IP address of gateway
+ :param tenant_id: (optional) tenant id of the subnet created
+ :param name: (optional) name of the subnet created
+ :returns: Subnet object
+ """
+ LOG.debug("subnet_create(): netid=%s, cidr=%s, ipver=%d, kwargs=%s"
+ % (network_id, cidr, ip_version, kwargs))
+ body = {'subnet':
+ {'network_id': network_id,
+ 'ip_version': ip_version,
+ 'cidr': cidr}}
+ body['subnet'].update(kwargs)
+ subnet = quantumclient(request).create_subnet(body=body).get('subnet')
+ return Subnet(subnet)
+
+
+def subnet_modify(request, subnet_id, **kwargs):
+ LOG.debug("subnet_modify(): subnetid=%s, kwargs=%s" % (subnet_id, kwargs))
+ body = {'subnet': kwargs}
+ subnet = quantumclient(request).update_subnet(subnet_id,
+ body=body).get('subnet')
+ return Subnet(subnet)
+
+
+def subnet_delete(request, subnet_id):
+ LOG.debug("subnet_delete(): subnetid=%s" % subnet_id)
+ quantumclient(request).delete_subnet(subnet_id)
+
+
+def port_list(request, **params):
+ LOG.debug("port_list(): params=%s" % (params))
+ ports = quantumclient(request).list_ports(**params).get('ports')
+ return [Port(p) for p in ports]
+
+
+def port_get(request, port_id, **params):
+ LOG.debug("port_get(): portid=%s, params=%s" % (port_id, params))
+ port = quantumclient(request).show_port(port_id, **params).get('port')
+ return Port(port)
+
+
+def port_create(request, network_id, **kwargs):
+ """
+ Create a port on a specified network.
+ :param request: request context
+ :param network_id: network id a subnet is created on
+ :param device_id: (optional) device id attached to the port
+ :param tenant_id: (optional) tenant id of the port created
+ :param name: (optional) name of the port created
+ :returns: Port object
+ """
+ LOG.debug("port_create(): netid=%s, kwargs=%s" % (network_id, kwargs))
+ body = {'port': {'network_id': network_id}}
+ body['port'].update(kwargs)
+ port = quantumclient(request).create_port(body=body).get('port')
+ return Port(port)
+
+
+def port_delete(request, port_id):
+ LOG.debug("port_delete(): portid=%s" % port_id)
+ quantumclient(request).delete_port(port_id)
+
+
+def port_modify(request, port_id, **kwargs):
+ LOG.debug("port_modify(): portid=%s, kwargs=%s" % (port_id, kwargs))
+ body = {'port': kwargs}
+ port = quantumclient(request).update_port(port_id, body=body).get('port')
+ return Port(port)
diff --git a/openstack_dashboard/api/swift.py b/openstack_dashboard/api/swift.py
new file mode 100644
index 000000000..b609b2e2f
--- /dev/null
+++ b/openstack_dashboard/api/swift.py
@@ -0,0 +1,265 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+import swiftclient
+
+from django.conf import settings
+from django.utils.translation import ugettext as _
+
+from horizon import exceptions
+
+from openstack_dashboard.api.base import url_for, APIDictWrapper
+
+
+LOG = logging.getLogger(__name__)
+FOLDER_DELIMITER = "/"
+
+
+class Container(APIDictWrapper):
+ pass
+
+
+class StorageObject(APIDictWrapper):
+ def __init__(self, apidict, container_name, orig_name=None, data=None):
+ super(StorageObject, self).__init__(apidict)
+ self.container_name = container_name
+ self.orig_name = orig_name
+ self.data = data
+
+
+class PseudoFolder(APIDictWrapper):
+ """
+ Wrapper to smooth out discrepencies between swift "subdir" items
+ and swift pseudo-folder objects.
+ """
+
+ def __init__(self, apidict, container_name):
+ super(PseudoFolder, self).__init__(apidict)
+ self.container_name = container_name
+
+ def _has_content_type(self):
+ content_type = self._apidict.get("content_type", None)
+ return content_type == "application/directory"
+
+ @property
+ def name(self):
+ if self._has_content_type():
+ return self._apidict['name']
+ return self.subdir.rstrip(FOLDER_DELIMITER)
+
+ @property
+ def bytes(self):
+ if self._has_content_type():
+ return self._apidict['bytes']
+ return None
+
+ @property
+ def content_type(self):
+ return "application/directory"
+
+
+def _objectify(items, container_name):
+ """ Splits a listing of objects into their appropriate wrapper classes. """
+ objects = {}
+ subdir_markers = []
+
+ # Deal with objects and object pseudo-folders first, save subdirs for later
+ for item in items:
+ if item.get("content_type", None) == "application/directory":
+ objects[item['name']] = PseudoFolder(item, container_name)
+ elif item.get("subdir", None) is not None:
+ subdir_markers.append(PseudoFolder(item, container_name))
+ else:
+ objects[item['name']] = StorageObject(item, container_name)
+ # Revisit subdirs to see if we have any non-duplicates
+ for item in subdir_markers:
+ if item.name not in objects.keys():
+ objects[item.name] = item
+ return objects.values()
+
+
+def swift_api(request):
+ endpoint = url_for(request, 'object-store')
+ LOG.debug('Swift connection created using token "%s" and url "%s"'
+ % (request.user.token.id, endpoint))
+ return swiftclient.client.Connection(None,
+ request.user.username,
+ None,
+ preauthtoken=request.user.token.id,
+ preauthurl=endpoint,
+ auth_version="2.0")
+
+
+def swift_container_exists(request, container_name):
+ try:
+ swift_api(request).head_container(container_name)
+ return True
+ except swiftclient.client.ClientException:
+ return False
+
+
+def swift_object_exists(request, container_name, object_name):
+ try:
+ swift_api(request).head_object(container_name, object_name)
+ return True
+ except swiftclient.client.ClientException:
+ return False
+
+
+def swift_get_containers(request, marker=None):
+ limit = getattr(settings, 'API_RESULT_LIMIT', 1000)
+ headers, containers = swift_api(request).get_account(limit=limit + 1,
+ marker=marker,
+ full_listing=True)
+ container_objs = [Container(c) for c in containers]
+ if(len(container_objs) > limit):
+ return (container_objs[0:-1], True)
+ else:
+ return (container_objs, False)
+
+
+def swift_create_container(request, name):
+ if swift_container_exists(request, name):
+ raise exceptions.AlreadyExists(name, 'container')
+ swift_api(request).put_container(name)
+ return Container({'name': name})
+
+
+def swift_delete_container(request, name):
+ swift_api(request).delete_container(name)
+ return True
+
+
+def swift_get_objects(request, container_name, prefix=None, marker=None,
+ limit=None):
+ limit = limit or getattr(settings, 'API_RESULT_LIMIT', 1000)
+ kwargs = dict(prefix=prefix,
+ marker=marker,
+ limit=limit + 1,
+ delimiter=FOLDER_DELIMITER,
+ full_listing=True)
+ headers, objects = swift_api(request).get_container(container_name,
+ **kwargs)
+ object_objs = _objectify(objects, container_name)
+
+ if(len(object_objs) > limit):
+ return (object_objs[0:-1], True)
+ else:
+ return (object_objs, False)
+
+
+def swift_filter_objects(request, filter_string, container_name, prefix=None,
+ marker=None):
+ # FIXME(kewu): Swift currently has no real filtering API, thus the marker
+ # parameter here won't actually help the pagination. For now I am just
+ # getting the largest number of objects from a container and filtering
+ # based on those objects.
+ limit = 9999
+ objects = swift_get_objects(request,
+ container_name,
+ prefix=prefix,
+ marker=marker,
+ limit=limit)
+ filter_string_list = filter_string.lower().strip().split(' ')
+
+ def matches_filter(obj):
+ for q in filter_string_list:
+ return wildcard_search(obj.name.lower(), q)
+
+ return filter(matches_filter, objects[0])
+
+
+def wildcard_search(string, q):
+ q_list = q.split('*')
+ if all(map(lambda x: x == '', q_list)):
+ return True
+ elif q_list[0] not in string:
+ return False
+ else:
+ if q_list[0] == '':
+ tail = string
+ else:
+ head, delimiter, tail = string.partition(q_list[0])
+ return wildcard_search(tail, '*'.join(q_list[1:]))
+
+
+def swift_copy_object(request, orig_container_name, orig_object_name,
+ new_container_name, new_object_name):
+ try:
+ # FIXME(gabriel): The swift currently fails at unicode in the
+ # copy_to method, so to provide a better experience we check for
+ # unicode here and pre-empt with an error message rather than
+ # letting the call fail.
+ str(orig_container_name)
+ str(orig_object_name)
+ str(new_container_name)
+ str(new_object_name)
+ except UnicodeEncodeError:
+ raise exceptions.HorizonException(_("Unicode is not currently "
+ "supported for object copy."))
+
+ if swift_object_exists(request, new_container_name, new_object_name):
+ raise exceptions.AlreadyExists(new_object_name, 'object')
+
+ headers = {"X-Copy-From": FOLDER_DELIMITER.join([orig_container_name,
+ orig_object_name])}
+ return swift_api(request).put_object(new_container_name,
+ new_object_name,
+ None,
+ headers=headers)
+
+
+def swift_create_subfolder(request, container_name, folder_name):
+ headers = {'content-type': 'application/directory',
+ 'content-length': 0}
+ etag = swift_api(request).put_object(container_name,
+ folder_name,
+ None,
+ headers=headers)
+ obj_info = {'subdir': folder_name, 'etag': etag}
+ return PseudoFolder(obj_info, container_name)
+
+
+def swift_upload_object(request, container_name, object_name, object_file):
+ headers = {}
+ headers['X-Object-Meta-Orig-Filename'] = object_file.name
+ etag = swift_api(request).put_object(container_name,
+ object_name,
+ object_file,
+ headers=headers)
+ obj_info = {'name': object_name, 'bytes': object_file.size, 'etag': etag}
+ return StorageObject(obj_info, container_name)
+
+
+def swift_delete_object(request, container_name, object_name):
+ swift_api(request).delete_object(container_name, object_name)
+ return True
+
+
+def swift_get_object(request, container_name, object_name):
+ headers, data = swift_api(request).get_object(container_name, object_name)
+ orig_name = headers.get("x-object-meta-orig-filename")
+ obj_info = {'name': object_name, 'bytes': len(data)}
+ return StorageObject(obj_info,
+ container_name,
+ orig_name=orig_name,
+ data=data)
diff --git a/openstack_dashboard/context_processors.py b/openstack_dashboard/context_processors.py
new file mode 100644
index 000000000..4d715f36a
--- /dev/null
+++ b/openstack_dashboard/context_processors.py
@@ -0,0 +1,63 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.
+"""
+Context processors used by Horizon.
+"""
+
+import logging
+
+from django.conf import settings
+
+
+LOG = logging.getLogger(__name__)
+
+
+def openstack(request):
+ """ Context processor necessary for OpenStack Dashboard functionality.
+
+ The following variables are added to the request context:
+
+ ``authorized_tenants``
+ A list of tenant objects which the current user has access to.
+
+ ``regions``
+
+ A dictionary containing information about region support, the current
+ region, and available regions.
+ """
+ context = {}
+
+ # Auth/Keystone context
+ context.setdefault('authorized_tenants', [])
+ current_dash = request.horizon['dashboard']
+ needs_tenants = getattr(current_dash, 'supports_tenants', False)
+ if request.user.is_authenticated() and needs_tenants:
+ context['authorized_tenants'] = request.user.authorized_tenants
+
+ # Region context/support
+ available_regions = getattr(settings, 'AVAILABLE_REGIONS', [])
+ regions = {'support': len(available_regions) > 1,
+ 'current': {'endpoint': request.session.get('region_endpoint'),
+ 'name': request.session.get('region_name')},
+ 'available': [{'endpoint': region[0], 'name':region[1]} for
+ region in available_regions]}
+ context['regions'] = regions
+
+ return context
diff --git a/openstack_dashboard/dashboards/__init__.py b/openstack_dashboard/dashboards/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/__init__.py
diff --git a/openstack_dashboard/dashboards/admin/__init__.py b/openstack_dashboard/dashboards/admin/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/__init__.py
diff --git a/openstack_dashboard/dashboards/admin/dashboard.py b/openstack_dashboard/dashboards/admin/dashboard.py
new file mode 100644
index 000000000..5eaf66f8c
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/dashboard.py
@@ -0,0 +1,37 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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
+
+
+class SystemPanels(horizon.PanelGroup):
+ slug = "admin"
+ name = _("System Panel")
+ panels = ('overview', 'instances', 'volumes', 'services', 'flavors',
+ 'images', 'projects', 'users', 'quotas', 'networks',)
+
+
+class Admin(horizon.Dashboard):
+ name = _("Admin")
+ slug = "admin"
+ panels = (SystemPanels,)
+ default_panel = 'overview'
+ permissions = ('openstack.roles.admin',)
+
+
+horizon.register(Admin)
diff --git a/openstack_dashboard/dashboards/admin/flavors/__init__.py b/openstack_dashboard/dashboards/admin/flavors/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/flavors/__init__.py
diff --git a/openstack_dashboard/dashboards/admin/flavors/forms.py b/openstack_dashboard/dashboards/admin/flavors/forms.py
new file mode 100644
index 000000000..208d6f5ee
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/flavors/forms.py
@@ -0,0 +1,96 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import messages
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateFlavor(forms.SelfHandlingForm):
+ name = forms.CharField(max_length="25", label=_("Name"))
+ vcpus = forms.IntegerField(label=_("VCPUs"))
+ memory_mb = forms.IntegerField(label=_("RAM MB"))
+ disk_gb = forms.IntegerField(label=_("Root Disk GB"))
+ eph_gb = forms.IntegerField(label=_("Ephemeral Disk GB"))
+
+ def _get_new_flavor_id(self):
+ # TODO(gabriel): Get rid of this hack after flavor
+ # id handling is improved in Nova's API.
+ flavors = []
+ try:
+ flavors = api.nova.flavor_list(self.request)
+ except:
+ exceptions.handle(self.request,
+ _("Unable to get unique ID for new flavor."))
+ if flavors:
+ largest_id = max(flavors, key=lambda f: f.id).id
+ flavor_id = int(largest_id) + 1
+ else:
+ flavor_id = 1
+ return flavor_id
+
+ def handle(self, request, data):
+ try:
+ flavor = api.nova.flavor_create(request,
+ data['name'],
+ data['memory_mb'],
+ data['vcpus'],
+ data['disk_gb'],
+ self._get_new_flavor_id(),
+ ephemeral=data['eph_gb'])
+ msg = _('Created flavor "%s".') % data['name']
+ messages.success(request, msg)
+ return flavor
+ except:
+ exceptions.handle(request, _("Unable to create flavor."))
+
+
+class EditFlavor(CreateFlavor):
+ flavor_id = forms.IntegerField(widget=forms.widgets.HiddenInput)
+
+ def handle(self, request, data):
+ try:
+ # First mark the existing flavor as deleted.
+ api.nova.flavor_delete(request, data['flavor_id'])
+ # Then create a new flavor with the same name but a new ID.
+ # This is in the same try/except block as the delete call
+ # because if the delete fails the API will error out because
+ # active flavors can't have the same name.
+ flavor = api.nova.flavor_create(request,
+ data['name'],
+ data['memory_mb'],
+ data['vcpus'],
+ data['disk_gb'],
+ self._get_new_flavor_id(),
+ ephemeral=data['eph_gb'])
+ msg = _('Updated flavor "%s".') % data['name']
+ messages.success(request, msg)
+ return flavor
+ except:
+ exceptions.handle(request, _("Unable to update flavor."))
diff --git a/openstack_dashboard/dashboards/admin/flavors/panel.py b/openstack_dashboard/dashboards/admin/flavors/panel.py
new file mode 100644
index 000000000..2f769b029
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/flavors/panel.py
@@ -0,0 +1,33 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.admin import dashboard
+
+
+class Flavors(horizon.Panel):
+ name = _("Flavors")
+ slug = 'flavors'
+
+
+dashboard.Admin.register(Flavors)
diff --git a/openstack_dashboard/dashboards/admin/flavors/tables.py b/openstack_dashboard/dashboards/admin/flavors/tables.py
new file mode 100644
index 000000000..0658589d8
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/flavors/tables.py
@@ -0,0 +1,54 @@
+import logging
+
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import tables
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class DeleteFlavor(tables.DeleteAction):
+ data_type_singular = _("Flavor")
+ data_type_plural = _("Flavors")
+
+ def delete(self, request, obj_id):
+ api.flavor_delete(request, obj_id)
+
+
+class CreateFlavor(tables.LinkAction):
+ name = "create"
+ verbose_name = _("Create Flavor")
+ url = "horizon:admin:flavors:create"
+ classes = ("ajax-modal", "btn-create")
+
+
+class EditFlavor(tables.LinkAction):
+ name = "edit"
+ verbose_name = _("Edit Flavor")
+ url = "horizon:admin:flavors:edit"
+ classes = ("ajax-modal", "btn-edit")
+
+
+def get_size(flavor):
+ return _("%sMB") % flavor.ram
+
+
+class FlavorsTable(tables.DataTable):
+ name = tables.Column('name', verbose_name=_('Flavor Name'))
+ vcpus = tables.Column('vcpus', verbose_name=_('VCPUs'))
+ ram = tables.Column(get_size,
+ verbose_name=_('RAM'),
+ attrs={'data-type': 'size'})
+ disk = tables.Column('disk', verbose_name=_('Root Disk'))
+ ephemeral = tables.Column('OS-FLV-EXT-DATA:ephemeral',
+ verbose_name=_('Ephemeral Disk'))
+ flavor_id = tables.Column('id', verbose_name=('ID'))
+
+ class Meta:
+ name = "flavors"
+ verbose_name = _("Flavors")
+ table_actions = (CreateFlavor, DeleteFlavor)
+ row_actions = (EditFlavor, DeleteFlavor)
diff --git a/openstack_dashboard/dashboards/admin/flavors/templates/flavors/_create.html b/openstack_dashboard/dashboards/admin/flavors/templates/flavors/_create.html
new file mode 100644
index 000000000..da6777bbe
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/flavors/templates/flavors/_create.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}create_flavor_form{% endblock %}
+{% block form_action %}{% url horizon:admin:flavors:create %}{% endblock %}
+
+{% block modal_id %}create_flavor_modal{% endblock %}
+{% block modal-header %}{% trans "Create Flavor" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "From here you can define the sizing of a new flavor." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Flavor" %}" />
+ <a href="{% url horizon:admin:flavors:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/flavors/templates/flavors/_edit.html b/openstack_dashboard/dashboards/admin/flavors/templates/flavors/_edit.html
new file mode 100644
index 000000000..b249ff027
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/flavors/templates/flavors/_edit.html
@@ -0,0 +1,26 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}edit_flavor_form{% endblock %}
+{% block form_action %}{% url horizon:admin:flavors:edit flavor_id %}{% endblock %}
+
+{% block modal_id %}edit_flavor_modal{% endblock %}
+{% block modal-header %}{% trans "Edit Flavor" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "From here you can alter the sizing of the current flavor." %}</p>
+ <p>{% trans "Note: this will not affect the resources allocated to any existing instances using this flavor." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Save" %}" />
+ <a href="{% url horizon:admin:flavors:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/flavors/templates/flavors/create.html b/openstack_dashboard/dashboards/admin/flavors/templates/flavors/create.html
new file mode 100644
index 000000000..377ed0e67
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/flavors/templates/flavors/create.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Create Flavor" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Create Flavor") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include "admin/flavors/_create.html" %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/flavors/templates/flavors/edit.html b/openstack_dashboard/dashboards/admin/flavors/templates/flavors/edit.html
new file mode 100644
index 000000000..8a634b44b
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/flavors/templates/flavors/edit.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Edit Flavor" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Edit Flavor") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include "admin/flavors/_edit.html" %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/flavors/templates/flavors/index.html b/openstack_dashboard/dashboards/admin/flavors/templates/flavors/index.html
new file mode 100644
index 000000000..3a306e57a
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/flavors/templates/flavors/index.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Flavors" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Flavors") %}
+{% endblock page_header %}
+
+{% block main %}
+ {{ table.render }}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/flavors/tests.py b/openstack_dashboard/dashboards/admin/flavors/tests.py
new file mode 100644
index 000000000..b6a01ac5d
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/flavors/tests.py
@@ -0,0 +1,81 @@
+from django import http
+from django.core.urlresolvers import reverse
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+class FlavorsTests(test.BaseAdminViewTests):
+ def test_create_new_flavor_when_none_exist(self):
+ flavor = self.flavors.first()
+ eph = getattr(flavor, 'OS-FLV-EXT-DATA:ephemeral')
+ self.mox.StubOutWithMock(api.nova, 'flavor_list')
+ self.mox.StubOutWithMock(api.nova, 'flavor_create')
+
+ # no pre-existing flavors
+ api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn([])
+ api.nova.flavor_create(IsA(http.HttpRequest),
+ flavor.name,
+ flavor.ram,
+ flavor.vcpus,
+ flavor.disk,
+ 1, # Flavor id 1 because there are no others.
+ ephemeral=eph).AndReturn(flavor)
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:flavors:create')
+ resp = self.client.get(url)
+ self.assertEqual(resp.status_code, 200)
+ self.assertTemplateUsed(resp, "admin/flavors/create.html")
+
+ data = {'name': flavor.name,
+ 'vcpus': flavor.vcpus,
+ 'memory_mb': flavor.ram,
+ 'disk_gb': flavor.disk,
+ 'eph_gb': eph}
+ resp = self.client.post(url, data)
+ self.assertRedirectsNoFollow(resp,
+ reverse("horizon:admin:flavors:index"))
+
+ def test_edit_flavor(self):
+ flavors = self.flavors.list()
+ flavor = self.flavors.first()
+ next_id = int(max(flavors, key=lambda f: f.id).id) + 1
+ eph = getattr(flavor, 'OS-FLV-EXT-DATA:ephemeral')
+ self.mox.StubOutWithMock(api.nova, 'flavor_list')
+ self.mox.StubOutWithMock(api.nova, 'flavor_get')
+ self.mox.StubOutWithMock(api.nova, 'flavor_delete')
+ self.mox.StubOutWithMock(api.nova, 'flavor_create')
+
+ # GET
+ api.nova.flavor_get(IsA(http.HttpRequest), flavor.id).AndReturn(flavor)
+
+ # POST
+ api.nova.flavor_get(IsA(http.HttpRequest), flavor.id).AndReturn(flavor)
+ api.nova.flavor_delete(IsA(http.HttpRequest), int(flavor.id))
+ api.nova.flavor_list(IsA(http.HttpRequest)) \
+ .AndReturn(flavors)
+ api.nova.flavor_create(IsA(http.HttpRequest),
+ flavor.name,
+ flavor.ram,
+ flavor.vcpus + 1,
+ flavor.disk,
+ next_id,
+ ephemeral=eph).AndReturn(flavor)
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:flavors:edit', args=[flavor.id])
+ resp = self.client.get(url)
+ self.assertEqual(resp.status_code, 200)
+ self.assertTemplateUsed(resp, "admin/flavors/edit.html")
+
+ data = {'flavor_id': flavor.id,
+ 'name': flavor.name,
+ 'vcpus': flavor.vcpus + 1,
+ 'memory_mb': flavor.ram,
+ 'disk_gb': flavor.disk,
+ 'eph_gb': eph}
+ resp = self.client.post(url, data)
+ self.assertRedirectsNoFollow(resp,
+ reverse("horizon:admin:flavors:index"))
diff --git a/openstack_dashboard/dashboards/admin/flavors/urls.py b/openstack_dashboard/dashboards/admin/flavors/urls.py
new file mode 100644
index 000000000..9a15a7026
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/flavors/urls.py
@@ -0,0 +1,29 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import patterns, url
+from .views import IndexView, CreateView, EditView
+
+
+urlpatterns = patterns('openstack_dashboard.dashboards.admin.flavors.views',
+ url(r'^$', IndexView.as_view(), name='index'),
+ url(r'^create/$', CreateView.as_view(), name='create'),
+ url(r'^(?P<id>[^/]+)/edit/$', EditView.as_view(), name='edit')
+)
diff --git a/openstack_dashboard/dashboards/admin/flavors/views.py b/openstack_dashboard/dashboards/admin/flavors/views.py
new file mode 100644
index 000000000..dba30684b
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/flavors/views.py
@@ -0,0 +1,82 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse_lazy
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import tables
+
+from openstack_dashboard import api
+from .forms import CreateFlavor, EditFlavor
+from .tables import FlavorsTable
+
+
+LOG = logging.getLogger(__name__)
+
+
+class IndexView(tables.DataTableView):
+ table_class = FlavorsTable
+ template_name = 'admin/flavors/index.html'
+
+ def get_data(self):
+ request = self.request
+ flavors = []
+ try:
+ flavors = api.flavor_list(request)
+ except:
+ exceptions.handle(request,
+ _('Unable to retrieve flavor list.'))
+ # Sort flavors by size
+ flavors.sort(key=lambda f: (f.vcpus, f.ram, f.disk))
+ return flavors
+
+
+class CreateView(forms.ModalFormView):
+ form_class = CreateFlavor
+ template_name = 'admin/flavors/create.html'
+ success_url = reverse_lazy('horizon:admin:flavors:index')
+
+
+class EditView(forms.ModalFormView):
+ form_class = EditFlavor
+ template_name = 'admin/flavors/edit.html'
+ success_url = reverse_lazy('horizon:admin:flavors:index')
+
+ def get_context_data(self, **kwargs):
+ context = super(EditView, self).get_context_data(**kwargs)
+ context['flavor_id'] = self.kwargs['id']
+ return context
+
+ def get_initial(self):
+ try:
+ flavor = api.nova.flavor_get(self.request, self.kwargs['id'])
+ except:
+ exceptions.handle(self.request,
+ _("Unable to retrieve flavor data."))
+ return {'flavor_id': flavor.id,
+ 'name': flavor.name,
+ 'vcpus': flavor.vcpus,
+ 'memory_mb': flavor.ram,
+ 'disk_gb': flavor.disk,
+ 'eph_gb': getattr(flavor, 'OS-FLV-EXT-DATA:ephemeral', None)}
diff --git a/openstack_dashboard/dashboards/admin/images/__init__.py b/openstack_dashboard/dashboards/admin/images/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/images/__init__.py
diff --git a/openstack_dashboard/dashboards/admin/images/forms.py b/openstack_dashboard/dashboards/admin/images/forms.py
new file mode 100644
index 000000000..55f61970d
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/images/forms.py
@@ -0,0 +1,26 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 openstack_dashboard.dashboards.project.images_and_snapshots \
+ .images import forms
+
+
+class AdminUpdateImageForm(forms.UpdateImageForm):
+ pass
diff --git a/openstack_dashboard/dashboards/admin/images/panel.py b/openstack_dashboard/dashboards/admin/images/panel.py
new file mode 100644
index 000000000..aa8d354d6
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/images/panel.py
@@ -0,0 +1,33 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.admin import dashboard
+
+
+class Images(horizon.Panel):
+ name = _("Images")
+ slug = 'images'
+
+
+dashboard.Admin.register(Images)
diff --git a/openstack_dashboard/dashboards/admin/images/tables.py b/openstack_dashboard/dashboards/admin/images/tables.py
new file mode 100644
index 000000000..6863bed0e
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/images/tables.py
@@ -0,0 +1,46 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 _
+
+from horizon import tables
+
+from openstack_dashboard.dashboards.project.images_and_snapshots \
+ .images.tables import (ImagesTable, EditImage, DeleteImage)
+
+
+class AdminDeleteImage(DeleteImage):
+ def allowed(self, request, image=None):
+ return True
+
+
+class AdminEditImage(EditImage):
+ url = "horizon:admin:images:update"
+
+ def allowed(self, request, image=None):
+ return True
+
+
+class AdminImagesTable(ImagesTable):
+ name = tables.Column("name",
+ link="horizon:admin:images:detail",
+ verbose_name=_("Image Name"))
+
+ class Meta:
+ name = "images"
+ verbose_name = _("Images")
+ table_actions = (AdminDeleteImage,)
+ row_actions = (AdminEditImage, AdminDeleteImage)
diff --git a/openstack_dashboard/dashboards/admin/images/templates/images/_update.html b/openstack_dashboard/dashboards/admin/images/templates/images/_update.html
new file mode 100644
index 000000000..764f6088b
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/images/templates/images/_update.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}update_image_form{% endblock %}
+{% block form_action %}{% url horizon:admin:images:update image.id %}{% endblock %}
+
+{% block modal_id %}update_image_modal{% endblock %}
+{% block modal-header %}{% trans "Update Image" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "From here you can modify different properties of an image." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Update Image" %}" />
+ <a href="{% url horizon:admin:images:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/images/templates/images/index.html b/openstack_dashboard/dashboards/admin/images/templates/images/index.html
new file mode 100644
index 000000000..b82d33775
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/images/templates/images/index.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Images" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Images") %}
+{% endblock page_header %}
+
+{% block main %}
+ {{ table.render }}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/images/templates/images/update.html b/openstack_dashboard/dashboards/admin/images/templates/images/update.html
new file mode 100644
index 000000000..e81c679bf
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/images/templates/images/update.html
@@ -0,0 +1,12 @@
+{% extends 'base.html' %}
+{% load i18n %}
+
+{% block title %}{% trans "Update Image" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Update Image") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'admin/images/_update.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/images/tests.py b/openstack_dashboard/dashboards/admin/images/tests.py
new file mode 100644
index 000000000..b33cbcd53
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/images/tests.py
@@ -0,0 +1,97 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 import http
+from django.conf import settings
+from django.core.urlresolvers import reverse
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+from .tables import AdminImagesTable
+
+
+class ImagesViewTest(test.BaseAdminViewTests):
+ @test.create_stubs({api: ('image_list_detailed',)})
+ def test_images_list(self):
+ api.image_list_detailed(IsA(http.HttpRequest),
+ marker=None) \
+ .AndReturn([self.images.list(),
+ False])
+ self.mox.ReplayAll()
+
+ res = self.client.get(
+ reverse('horizon:admin:images:index'))
+ self.assertTemplateUsed(res, 'admin/images/index.html')
+ self.assertEqual(len(res.context['images_table'].data),
+ len(self.images.list()))
+
+ @test.create_stubs({api: ('image_list_detailed',)})
+ def test_images_list_get_pagination(self):
+ api.image_list_detailed(IsA(http.HttpRequest),
+ marker=None) \
+ .AndReturn([self.images.list(),
+ True])
+ api.image_list_detailed(IsA(http.HttpRequest),
+ marker=None) \
+ .AndReturn([self.images.list()[:2],
+ True])
+ api.image_list_detailed(IsA(http.HttpRequest),
+ marker=self.images.list()[2].id) \
+ .AndReturn([self.images.list()[2:4],
+ True])
+ api.image_list_detailed(IsA(http.HttpRequest),
+ marker=self.images.list()[4].id) \
+ .AndReturn([self.images.list()[4:],
+ True])
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:images:index')
+ res = self.client.get(url)
+ # get all
+ self.assertEqual(len(res.context['images_table'].data),
+ len(self.images.list()))
+ self.assertTemplateUsed(res, 'admin/images/index.html')
+
+ page_size = getattr(settings, "API_RESULT_PAGE_SIZE", None)
+ settings.API_RESULT_PAGE_SIZE = 2
+
+ res = self.client.get(url)
+ # get first page with 2 items
+ self.assertEqual(len(res.context['images_table'].data),
+ settings.API_RESULT_PAGE_SIZE)
+
+ url = "?".join([reverse('horizon:admin:images:index'),
+ "=".join([AdminImagesTable._meta.pagination_param,
+ self.images.list()[2].id])])
+ res = self.client.get(url)
+ # get second page (items 2-4)
+ self.assertEqual(len(res.context['images_table'].data),
+ settings.API_RESULT_PAGE_SIZE)
+
+ url = "?".join([reverse('horizon:admin:images:index'),
+ "=".join([AdminImagesTable._meta.pagination_param,
+ self.images.list()[4].id])])
+ res = self.client.get(url)
+ # get third page (item 5)
+ self.assertEqual(len(res.context['images_table'].data),
+ 1)
+
+ # restore API_RESULT_PAGE_SIZE
+ if page_size:
+ settings.API_RESULT_PAGE_SIZE = page_size
+ else:
+ del settings.API_RESULT_PAGE_SIZE
diff --git a/openstack_dashboard/dashboards/admin/images/urls.py b/openstack_dashboard/dashboards/admin/images/urls.py
new file mode 100644
index 000000000..f29a67862
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/images/urls.py
@@ -0,0 +1,30 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import patterns, url
+
+from .views import IndexView, UpdateView, DetailView
+
+
+urlpatterns = patterns('openstack_dashboard.dashboards.admin.images.views',
+ url(r'^images/$', IndexView.as_view(), name='index'),
+ url(r'^(?P<image_id>[^/]+)/update/$', UpdateView.as_view(), name='update'),
+ url(r'^(?P<image_id>[^/]+)/detail/$', DetailView.as_view(), name='detail')
+)
diff --git a/openstack_dashboard/dashboards/admin/images/views.py b/openstack_dashboard/dashboards/admin/images/views.py
new file mode 100644
index 000000000..b27b19a6b
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/images/views.py
@@ -0,0 +1,68 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse_lazy
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tables
+
+from openstack_dashboard import api
+from openstack_dashboard.dashboards.project \
+ .images_and_snapshots.images import views
+from .tables import AdminImagesTable
+from .forms import AdminUpdateImageForm
+
+
+LOG = logging.getLogger(__name__)
+
+
+class IndexView(tables.DataTableView):
+ table_class = AdminImagesTable
+ template_name = 'admin/images/index.html'
+
+ def has_more_data(self, table):
+ return self._more
+
+ def get_data(self):
+ images = []
+ marker = self.request.GET.get(AdminImagesTable._meta.pagination_param,
+ None)
+ try:
+ images, self._more = api.image_list_detailed(self.request,
+ marker=marker)
+ except:
+ self._more = False
+ msg = _('Unable to retrieve image list.')
+ exceptions.handle(self.request, msg)
+ return images
+
+
+class UpdateView(views.UpdateView):
+ template_name = 'admin/images/update.html'
+ form_class = AdminUpdateImageForm
+ success_url = reverse_lazy('horizon:admin:images:index')
+
+
+class DetailView(views.DetailView):
+ """ Admin placeholder for image detail view. """
+ pass
diff --git a/openstack_dashboard/dashboards/admin/instances/__init__.py b/openstack_dashboard/dashboards/admin/instances/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/instances/__init__.py
diff --git a/openstack_dashboard/dashboards/admin/instances/panel.py b/openstack_dashboard/dashboards/admin/instances/panel.py
new file mode 100644
index 000000000..3e4fd5110
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/instances/panel.py
@@ -0,0 +1,34 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.admin import dashboard
+
+
+class Instances(horizon.Panel):
+ name = _("Instances")
+ slug = 'instances'
+ permissions = ('openstack.roles.admin',)
+
+
+dashboard.Admin.register(Instances)
diff --git a/openstack_dashboard/dashboards/admin/instances/tables.py b/openstack_dashboard/dashboards/admin/instances/tables.py
new file mode 100644
index 000000000..cc115ae3b
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/instances/tables.py
@@ -0,0 +1,100 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Openstack, LLC
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.template.defaultfilters import title
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import tables
+from horizon.utils.filters import replace_underscores
+
+from openstack_dashboard import api
+from openstack_dashboard.dashboards.project.instances.tables import (
+ TerminateInstance, EditInstance, ConsoleLink, LogLink, CreateSnapshot,
+ TogglePause, ToggleSuspend, RebootInstance, get_size, UpdateRow,
+ get_ips, get_power_state)
+
+LOG = logging.getLogger(__name__)
+
+
+class AdminUpdateRow(UpdateRow):
+ def get_data(self, request, instance_id):
+ instance = super(AdminUpdateRow, self).get_data(request, instance_id)
+ tenant = api.keystone.tenant_get(request,
+ instance.tenant_id,
+ admin=True)
+ instance.tenant_name = getattr(tenant, "name", None)
+ return instance
+
+
+class AdminInstancesTable(tables.DataTable):
+ TASK_STATUS_CHOICES = (
+ (None, True),
+ ("none", True)
+ )
+ STATUS_CHOICES = (
+ ("active", True),
+ ("shutoff", True),
+ ("suspended", True),
+ ("paused", True),
+ ("error", False),
+ )
+ TASK_DISPLAY_CHOICES = (
+ ("image_snapshot", "Snapshotting"),
+ )
+ tenant = tables.Column("tenant_name", verbose_name=_("Project Name"))
+ # NOTE(gabriel): Commenting out the user column because all we have
+ # is an ID, and correlating that at production scale using our current
+ # techniques isn't practical. It can be added back in when we have names
+ # returned in a practical manner by the API.
+ #user = tables.Column("user_id", verbose_name=_("User"))
+ host = tables.Column("OS-EXT-SRV-ATTR:host",
+ verbose_name=_("Host"),
+ classes=('nowrap-col',))
+ name = tables.Column("name",
+ link=("horizon:project:instances:detail"),
+ verbose_name=_("Instance Name"))
+ ip = tables.Column(get_ips, verbose_name=_("IP Address"))
+ size = tables.Column(get_size,
+ verbose_name=_("Size"),
+ classes=('nowrap-col',),
+ attrs={'data-type': 'size'})
+ status = tables.Column("status",
+ filters=(title, replace_underscores),
+ verbose_name=_("Status"),
+ status=True,
+ status_choices=STATUS_CHOICES)
+ task = tables.Column("OS-EXT-STS:task_state",
+ verbose_name=_("Task"),
+ filters=(title, replace_underscores),
+ status=True,
+ status_choices=TASK_STATUS_CHOICES,
+ display_choices=TASK_DISPLAY_CHOICES)
+ state = tables.Column(get_power_state,
+ filters=(title, replace_underscores),
+ verbose_name=_("Power State"))
+
+ class Meta:
+ name = "instances"
+ verbose_name = _("Instances")
+ status_columns = ["status", "task"]
+ table_actions = (TerminateInstance,)
+ row_class = AdminUpdateRow
+ row_actions = (EditInstance, ConsoleLink, LogLink, CreateSnapshot,
+ TogglePause, ToggleSuspend, RebootInstance,
+ TerminateInstance)
diff --git a/openstack_dashboard/dashboards/admin/instances/templates/instances/index.html b/openstack_dashboard/dashboards/admin/instances/templates/instances/index.html
new file mode 100644
index 000000000..43f9d1c9d
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/instances/templates/instances/index.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Instances" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("All Instances") %}
+{% endblock page_header %}
+
+{% block main %}
+ {{ table.render }}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/instances/tests.py b/openstack_dashboard/dashboards/admin/instances/tests.py
new file mode 100644
index 000000000..475673689
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/instances/tests.py
@@ -0,0 +1,140 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 import http
+from django.core.urlresolvers import reverse
+from django.utils.datastructures import SortedDict
+
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+class InstanceViewTest(test.BaseAdminViewTests):
+ @test.create_stubs({api.nova: ('flavor_list', 'server_list',),
+ api.keystone: ('tenant_list',)})
+ def test_index(self):
+ servers = self.servers.list()
+ flavors = self.flavors.list()
+ tenants = self.tenants.list()
+ api.keystone.tenant_list(IsA(http.HttpRequest), admin=True).\
+ AndReturn(tenants)
+ api.nova.server_list(IsA(http.HttpRequest),
+ all_tenants=True).AndReturn(servers)
+ api.nova.flavor_list(IsA(http.HttpRequest)).AndReturn(flavors)
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:admin:instances:index'))
+ self.assertTemplateUsed(res, 'admin/instances/index.html')
+ instances = res.context['table'].data
+ self.assertItemsEqual(instances, servers)
+
+ @test.create_stubs({api.nova: ('flavor_list', 'flavor_get',
+ 'server_list',),
+ api.keystone: ('tenant_list',)})
+ def test_index_flavor_list_exception(self):
+ servers = self.servers.list()
+ tenants = self.tenants.list()
+ flavors = self.flavors.list()
+ full_flavors = SortedDict([(f.id, f) for f in flavors])
+
+ api.nova.server_list(IsA(http.HttpRequest),
+ all_tenants=True).AndReturn(servers)
+ api.nova.flavor_list(IsA(http.HttpRequest)). \
+ AndRaise(self.exceptions.nova)
+ api.keystone.tenant_list(IsA(http.HttpRequest), admin=True).\
+ AndReturn(tenants)
+ for server in servers:
+ api.nova.flavor_get(IsA(http.HttpRequest), server.flavor["id"]). \
+ AndReturn(full_flavors[server.flavor["id"]])
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:admin:instances:index'))
+ self.assertTemplateUsed(res, 'admin/instances/index.html')
+ instances = res.context['table'].data
+ self.assertItemsEqual(instances, servers)
+
+ @test.create_stubs({api.nova: ('flavor_list', 'flavor_get',
+ 'server_list',),
+ api.keystone: ('tenant_list',)})
+ def test_index_flavor_get_exception(self):
+ servers = self.servers.list()
+ flavors = self.flavors.list()
+ tenants = self.tenants.list()
+ max_id = max([int(flavor.id) for flavor in flavors])
+ for server in servers:
+ max_id += 1
+ server.flavor["id"] = max_id
+
+ api.nova.server_list(IsA(http.HttpRequest),
+ all_tenants=True).AndReturn(servers)
+ api.nova.flavor_list(IsA(http.HttpRequest)). \
+ AndReturn(flavors)
+ api.keystone.tenant_list(IsA(http.HttpRequest), admin=True).\
+ AndReturn(tenants)
+ for server in servers:
+ api.nova.flavor_get(IsA(http.HttpRequest), server.flavor["id"]). \
+ AndRaise(self.exceptions.nova)
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:admin:instances:index'))
+ instances = res.context['table'].data
+ self.assertTemplateUsed(res, 'admin/instances/index.html')
+ self.assertMessageCount(res, error=len(servers))
+ self.assertItemsEqual(instances, servers)
+
+ @test.create_stubs({api.nova: ('server_list',)})
+ def test_index_server_list_exception(self):
+ api.nova.server_list(IsA(http.HttpRequest),
+ all_tenants=True).AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:admin:instances:index'))
+ self.assertTemplateUsed(res, 'admin/instances/index.html')
+ self.assertEqual(len(res.context['instances_table'].data), 0)
+
+ @test.create_stubs({api: ('server_get', 'flavor_get',),
+ api.keystone: ('tenant_get',)})
+ def test_ajax_loading_instances(self):
+ server = self.servers.first()
+ flavor = self.flavors.list()[0]
+ tenant = self.tenants.list()[0]
+
+ api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
+ api.flavor_get(IsA(http.HttpRequest),
+ server.flavor['id']).AndReturn(flavor)
+ api.keystone.tenant_get(IsA(http.HttpRequest),
+ server.tenant_id,
+ admin=True).AndReturn(tenant)
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:instances:index') + \
+ "?action=row_update&table=instances&obj_id=" + server.id
+
+ res = self.client.get(url, {},
+ HTTP_X_REQUESTED_WITH='XMLHttpRequest')
+ self.assertTemplateUsed(res, "horizon/common/_data_table_row.html")
+
+ self.assertContains(res, "test_tenant", 1, 200)
+ self.assertContains(res, "instance-host", 1, 200)
+ self.assertContains(res, "server_1", 1, 200)
+ self.assertContains(res, "10.0.0.1", 1, 200)
+ self.assertContains(res, "512MB RAM | 1 VCPU | 0 Disk", 1, 200)
+ self.assertContains(res, "Active", 1, 200)
+ self.assertContains(res, "Running", 1, 200)
diff --git a/openstack_dashboard/dashboards/admin/instances/urls.py b/openstack_dashboard/dashboards/admin/instances/urls.py
new file mode 100644
index 000000000..3e18d0c63
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/instances/urls.py
@@ -0,0 +1,34 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import url, patterns
+
+from .views import DetailView, AdminIndexView
+
+
+INSTANCES = r'^(?P<instance_id>[^/]+)/%s$'
+
+
+urlpatterns = patterns('openstack_dashboard.dashboards.admin.instances.views',
+ url(r'^$', AdminIndexView.as_view(), name='index'),
+ url(INSTANCES % 'detail', DetailView.as_view(), name='detail'),
+ url(INSTANCES % 'console', 'console', name='console'),
+ url(INSTANCES % 'vnc', 'vnc', name='vnc'),
+)
diff --git a/openstack_dashboard/dashboards/admin/instances/views.py b/openstack_dashboard/dashboards/admin/instances/views.py
new file mode 100644
index 000000000..a11f96f5d
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/instances/views.py
@@ -0,0 +1,84 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Openstack, LLC
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.utils.datastructures import SortedDict
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tables
+
+from openstack_dashboard import api
+from openstack_dashboard.dashboards.admin.instances.tables import \
+ AdminInstancesTable
+from openstack_dashboard.dashboards.project.instances.views import \
+ console, DetailView, vnc
+
+LOG = logging.getLogger(__name__)
+
+
+class AdminIndexView(tables.DataTableView):
+ table_class = AdminInstancesTable
+ template_name = 'admin/instances/index.html'
+
+ def get_data(self):
+ instances = []
+ try:
+ instances = api.nova.server_list(self.request, all_tenants=True)
+ except:
+ exceptions.handle(self.request,
+ _('Unable to retrieve instance list.'))
+ if instances:
+ # Gather our flavors to correlate against IDs
+ try:
+ flavors = api.nova.flavor_list(self.request)
+ except:
+ # If fails to retrieve flavor list, creates an empty list.
+ flavors = []
+
+ # Gather our tenants to correlate against IDs
+ try:
+ tenants = api.keystone.tenant_list(self.request, admin=True)
+ except:
+ tenants = []
+ msg = _('Unable to retrieve instance tenant information.')
+ exceptions.handle(self.request, msg)
+
+ full_flavors = SortedDict([(f.id, f) for f in flavors])
+ tenant_dict = SortedDict([(t.id, t) for t in tenants])
+ # Loop through instances to get flavor and tenant info.
+ for inst in instances:
+ flavor_id = inst.flavor["id"]
+ try:
+ if flavor_id in full_flavors:
+ inst.full_flavor = full_flavors[flavor_id]
+ else:
+ # If the flavor_id is not in full_flavors list,
+ # gets it via nova api.
+ inst.full_flavor = api.nova.flavor_get(
+ self.request, flavor_id)
+ except:
+ msg = _('Unable to retrieve instance size information.')
+ exceptions.handle(self.request, msg)
+ tenant = tenant_dict.get(inst.tenant_id, None)
+ inst.tenant_name = getattr(tenant, "name", None)
+ return instances
diff --git a/openstack_dashboard/dashboards/admin/models.py b/openstack_dashboard/dashboards/admin/models.py
new file mode 100644
index 000000000..6313a32fa
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/models.py
@@ -0,0 +1,23 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.
+
+"""
+Stub file to work around django bug: https://code.djangoproject.com/ticket/7198
+"""
diff --git a/openstack_dashboard/dashboards/admin/networks/__init__.py b/openstack_dashboard/dashboards/admin/networks/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/__init__.py
diff --git a/openstack_dashboard/dashboards/admin/networks/forms.py b/openstack_dashboard/dashboards/admin/networks/forms.py
new file mode 100644
index 000000000..5a969bfec
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/forms.py
@@ -0,0 +1,90 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import messages
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateNetwork(forms.SelfHandlingForm):
+ name = forms.CharField(max_length=255,
+ label=_("Name"),
+ required=False)
+ tenant_id = forms.ChoiceField(label=_("Project"))
+ shared = forms.BooleanField(label=_("Shared"),
+ initial=False, required=False)
+
+ @classmethod
+ def _instantiate(cls, request, *args, **kwargs):
+ return cls(request, *args, **kwargs)
+
+ def __init__(self, request, *args, **kwargs):
+ super(CreateNetwork, self).__init__(request, *args, **kwargs)
+ tenant_choices = [('', _("Select a project"))]
+ for tenant in api.keystone.tenant_list(request, admin=True):
+ if tenant.enabled:
+ tenant_choices.append((tenant.id, tenant.name))
+ self.fields['tenant_id'].choices = tenant_choices
+
+ def handle(self, request, data):
+ try:
+ network = api.quantum.network_create(request,
+ name=data['name'],
+ tenant_id=data['tenant_id'],
+ shared=data['shared'])
+ msg = _('Network %s was successfully created.') % data['name']
+ LOG.debug(msg)
+ messages.success(request, msg)
+ return network
+ except:
+ redirect = reverse('horizon:admin:networks:index')
+ msg = _('Failed to create network %s') % data['name']
+ exceptions.handle(request, msg, redirect=redirect)
+
+
+class UpdateNetwork(forms.SelfHandlingForm):
+ name = forms.CharField(label=_("Name"), required=False)
+ tenant_id = forms.CharField(widget=forms.HiddenInput)
+ network_id = forms.CharField(label=_("ID"),
+ widget=forms.TextInput(
+ attrs={'readonly': 'readonly'}))
+ shared = forms.BooleanField(label=_("Shared"), required=False)
+ failure_url = 'horizon:admin:networks:index'
+
+ def handle(self, request, data):
+ try:
+ network = api.quantum.network_modify(request, data['network_id'],
+ name=data['name'],
+ shared=data['shared'])
+ msg = _('Network %s was successfully updated.') % data['name']
+ LOG.debug(msg)
+ messages.success(request, msg)
+ return network
+ except:
+ msg = _('Failed to update network %s') % data['name']
+ LOG.info(msg)
+ redirect = reverse(self.failure_url)
+ exceptions.handle(request, msg, redirect=redirect)
diff --git a/openstack_dashboard/dashboards/admin/networks/panel.py b/openstack_dashboard/dashboards/admin/networks/panel.py
new file mode 100644
index 000000000..22774c6c6
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/panel.py
@@ -0,0 +1,29 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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.admin import dashboard
+
+
+class Networks(horizon.Panel):
+ name = _("Networks")
+ slug = 'networks'
+ permissions = ('openstack.services.network',)
+
+dashboard.Admin.register(Networks)
diff --git a/openstack_dashboard/dashboards/admin/networks/ports/__init__.py b/openstack_dashboard/dashboards/admin/networks/ports/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/ports/__init__.py
diff --git a/openstack_dashboard/dashboards/admin/networks/ports/forms.py b/openstack_dashboard/dashboards/admin/networks/ports/forms.py
new file mode 100644
index 000000000..19d0838cd
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/ports/forms.py
@@ -0,0 +1,93 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import messages
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreatePort(forms.SelfHandlingForm):
+ network_name = forms.CharField(label=_("Network Name"),
+ widget=forms.TextInput(
+ attrs={'readonly': 'readonly'}))
+ network_id = forms.CharField(label=_("Network ID"),
+ widget=forms.TextInput(
+ attrs={'readonly': 'readonly'}))
+ name = forms.CharField(max_length=255,
+ label=_("Name"),
+ required=False)
+ device_id = forms.CharField(max_length=100, label=_("Device ID"),
+ help_text='Device ID attached to the port',
+ required=False)
+
+ def handle(self, request, data):
+ try:
+ # We must specify tenant_id of the network which a subnet is
+ # created for if admin user does not belong to the tenant.
+ network = api.quantum.network_get(request, data['network_id'])
+ data['tenant_id'] = network.tenant_id
+
+ port = api.quantum.port_create(request, **data)
+ msg = _('Port %s was successfully created.') % port['id']
+ LOG.debug(msg)
+ messages.success(request, msg)
+ return port
+ except:
+ msg = _('Failed to create a port for network %s') \
+ % data['network_id']
+ LOG.info(msg)
+ redirect = reverse('horizon:admin:networks:detail',
+ args=(data['network_id'],))
+ exceptions.handle(request, msg, redirect=redirect)
+
+
+class UpdatePort(forms.SelfHandlingForm):
+ network_id = forms.CharField(widget=forms.HiddenInput())
+ tenant_id = forms.CharField(widget=forms.HiddenInput())
+ port_id = forms.CharField(widget=forms.HiddenInput())
+ name = forms.CharField(max_length=255,
+ label=_("Name"),
+ required=False)
+ device_id = forms.CharField(max_length=100, label=_("Device ID"),
+ help_text='Device ID attached to the port',
+ required=False)
+
+ def handle(self, request, data):
+ try:
+ LOG.debug('params = %s' % data)
+ port = api.quantum.port_modify(request, data['port_id'],
+ name=data['name'],
+ device_id=data['device_id'])
+ msg = _('Port %s was successfully updated.') % data['port_id']
+ LOG.debug(msg)
+ messages.success(request, msg)
+ return port
+ except Exception:
+ msg = _('Failed to update port %s') % data['port_id']
+ LOG.info(msg)
+ redirect = reverse('horizon:admin:networks:detail',
+ args=[data['network_id']])
+ exceptions.handle(request, msg, redirect=redirect)
diff --git a/openstack_dashboard/dashboards/admin/networks/ports/tables.py b/openstack_dashboard/dashboards/admin/networks/ports/tables.py
new file mode 100644
index 000000000..e8a356256
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/ports/tables.py
@@ -0,0 +1,85 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tables
+
+from openstack_dashboard import api
+from openstack_dashboard.dashboards.project.networks.ports.tables import \
+ get_fixed_ips, get_attached
+
+
+LOG = logging.getLogger(__name__)
+
+
+class DeletePort(tables.DeleteAction):
+ data_type_singular = _("Port")
+ data_type_plural = _("Ports")
+
+ def delete(self, request, obj_id):
+ try:
+ api.quantum.port_delete(request, obj_id)
+ except:
+ msg = _('Failed to delete subnet %s') % obj_id
+ LOG.info(msg)
+ network_id = self.table.kwargs['network_id']
+ redirect = reverse('horizon:admin:networks:detail',
+ args=[network_id])
+ exceptions.handle(request, msg, redirect=redirect)
+
+
+class CreatePort(tables.LinkAction):
+ name = "create"
+ verbose_name = _("Create Port")
+ url = "horizon:admin:networks:addport"
+ classes = ("ajax-modal", "btn-create")
+
+ def get_link_url(self, datum=None):
+ network_id = self.table.kwargs['network_id']
+ return reverse(self.url, args=(network_id,))
+
+
+class UpdatePort(tables.LinkAction):
+ name = "update"
+ verbose_name = _("Edit Port")
+ url = "horizon:admin:networks:editport"
+ classes = ("ajax-modal", "btn-edit")
+
+ def get_link_url(self, port):
+ network_id = self.table.kwargs['network_id']
+ return reverse(self.url, args=(network_id, port.id))
+
+
+class PortsTable(tables.DataTable):
+ name = tables.Column("name",
+ verbose_name=_("Name"),
+ link="horizon:admin:networks:ports:detail")
+ fixed_ips = tables.Column(get_fixed_ips, verbose_name=_("Fixed IPs"))
+ device_id = tables.Column(get_attached, verbose_name=_("Device Attached"))
+ status = tables.Column("status", verbose_name=_("Status"))
+ admin_state = tables.Column("admin_state",
+ verbose_name=_("Admin State"))
+
+ class Meta:
+ name = "ports"
+ verbose_name = _("Ports")
+ table_actions = (CreatePort, DeletePort)
+ row_actions = (UpdatePort, DeletePort,)
diff --git a/openstack_dashboard/dashboards/admin/networks/ports/tabs.py b/openstack_dashboard/dashboards/admin/networks/ports/tabs.py
new file mode 100644
index 000000000..2fda2ba95
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/ports/tabs.py
@@ -0,0 +1,49 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tabs
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class OverviewTab(tabs.Tab):
+ name = _("Overview")
+ slug = "overview"
+ template_name = "project/networks/ports/_detail_overview.html"
+
+ def get_context_data(self, request):
+ port_id = self.tab_group.kwargs['port_id']
+ try:
+ port = api.quantum.port_get(self.request, port_id)
+ except:
+ redirect = reverse('horizon:admin:networks:index')
+ msg = _('Unable to retrieve port details.')
+ exceptions.handle(request, msg, redirect=redirect)
+ return {'port': port}
+
+
+class PortDetailTabs(tabs.TabGroup):
+ slug = "port_details"
+ tabs = (OverviewTab,)
diff --git a/openstack_dashboard/dashboards/admin/networks/ports/urls.py b/openstack_dashboard/dashboards/admin/networks/ports/urls.py
new file mode 100644
index 000000000..b485427b3
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/ports/urls.py
@@ -0,0 +1,28 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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.defaults import patterns, url
+
+from openstack_dashboard.dashboards.project.networks.ports.views import \
+ DetailView
+
+PORTS = r'^(?P<port_id>[^/]+)/%s$'
+VIEW_MOD = 'openstack_dashboard.dashboards.admin.networks.ports.views'
+
+
+urlpatterns = patterns(VIEW_MOD,
+ url(PORTS % 'detail', DetailView.as_view(), name='detail')
+)
diff --git a/openstack_dashboard/dashboards/admin/networks/ports/views.py b/openstack_dashboard/dashboards/admin/networks/ports/views.py
new file mode 100644
index 000000000..43fad6390
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/ports/views.py
@@ -0,0 +1,99 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+
+from openstack_dashboard import api
+from .forms import CreatePort, UpdatePort
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateView(forms.ModalFormView):
+ form_class = CreatePort
+ template_name = 'admin/networks/ports/create.html'
+ success_url = 'horizon:admin:networks:detail'
+
+ def get_success_url(self):
+ return reverse(self.success_url,
+ args=(self.kwargs['network_id'],))
+
+ def get_object(self):
+ if not hasattr(self, "_object"):
+ try:
+ network_id = self.kwargs["network_id"]
+ self._object = api.quantum.network_get(self.request,
+ network_id)
+ except:
+ redirect = reverse("horizon:admin:networks:detail",
+ args=(self.kwargs['network_id'],))
+ msg = _("Unable to retrieve network.")
+ exceptions.handle(self.request, msg, redirect=redirect)
+ return self._object
+
+ def get_context_data(self, **kwargs):
+ context = super(CreateView, self).get_context_data(**kwargs)
+ context['network'] = self.get_object()
+ return context
+
+ def get_initial(self):
+ network = self.get_object()
+ return {"network_id": self.kwargs['network_id'],
+ "network_name": network.name}
+
+
+class UpdateView(forms.ModalFormView):
+ form_class = UpdatePort
+ template_name = 'admin/networks/ports/update.html'
+ context_object_name = 'port'
+ success_url = 'horizon:admin:networks:detail'
+
+ def get_success_url(self):
+ return reverse(self.success_url,
+ args=(self.kwargs['network_id'],))
+
+ def _get_object(self, *args, **kwargs):
+ if not hasattr(self, "_object"):
+ port_id = self.kwargs['port_id']
+ try:
+ self._object = api.quantum.port_get(self.request, port_id)
+ except:
+ redirect = reverse("horizon:admin:networks:detail",
+ args=(self.kwargs['network_id'],))
+ msg = _('Unable to retrieve port details')
+ exceptions.handle(self.request, msg, redirect=redirect)
+ return self._object
+
+ def get_context_data(self, **kwargs):
+ context = super(UpdateView, self).get_context_data(**kwargs)
+ port = self._get_object()
+ context['port_id'] = port['id']
+ context['network_id'] = port['network_id']
+ return context
+
+ def get_initial(self):
+ port = self._get_object()
+ return {'port_id': port['id'],
+ 'network_id': port['network_id'],
+ 'tenant_id': port['tenant_id'],
+ 'name': port['name'],
+ 'device_id': port['device_id']}
diff --git a/openstack_dashboard/dashboards/admin/networks/subnets/__init__.py b/openstack_dashboard/dashboards/admin/networks/subnets/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/subnets/__init__.py
diff --git a/openstack_dashboard/dashboards/admin/networks/subnets/forms.py b/openstack_dashboard/dashboards/admin/networks/subnets/forms.py
new file mode 100644
index 000000000..2a4ab362d
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/subnets/forms.py
@@ -0,0 +1,53 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import forms
+from horizon import exceptions
+
+from openstack_dashboard import api
+from openstack_dashboard.dashboards.project.networks.subnets import \
+ forms as user_forms
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateSubnet(user_forms.CreateSubnet):
+ failure_url = 'horizon:admin:networks:detail'
+
+ def handle(self, request, data):
+ try:
+ # We must specify tenant_id of the network which a subnet is
+ # created for if admin user does not belong to the tenant.
+ network = api.quantum.network_get(request, data['network_id'])
+ data['tenant_id'] = network.tenant_id
+ except:
+ msg = _('Failed to retrieve network %s for a subnet') \
+ % data['network_id']
+ LOG.info(msg)
+ redirect = reverse(self.failure_url, args=[data['network_id']])
+ exceptions.handle(request, msg, redirect=redirect)
+ return super(CreateSubnet, self).handle(request, data)
+
+
+class UpdateSubnet(user_forms.UpdateSubnet):
+ tenant_id = forms.CharField(widget=forms.HiddenInput())
+ failure_url = 'horizon:admin:networks:detail'
diff --git a/openstack_dashboard/dashboards/admin/networks/subnets/tables.py b/openstack_dashboard/dashboards/admin/networks/subnets/tables.py
new file mode 100644
index 000000000..874f26eb1
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/subnets/tables.py
@@ -0,0 +1,83 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tables
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class DeleteSubnet(tables.DeleteAction):
+ data_type_singular = _("Subnet")
+ data_type_plural = _("Subnets")
+
+ def delete(self, request, obj_id):
+ try:
+ api.quantum.subnet_delete(request, obj_id)
+ except:
+ msg = _('Failed to delete subnet %s') % obj_id
+ LOG.info(msg)
+ network_id = self.table.kwargs['network_id']
+ redirect = reverse('horizon:admin:networks:detail',
+ args=[network_id])
+ exceptions.handle(request, msg, redirect=redirect)
+
+
+class CreateSubnet(tables.LinkAction):
+ name = "create"
+ verbose_name = _("Create Subnet")
+ url = "horizon:admin:networks:addsubnet"
+ classes = ("ajax-modal", "btn-create")
+
+ def get_link_url(self, datum=None):
+ network_id = self.table.kwargs['network_id']
+ return reverse(self.url, args=(network_id,))
+
+
+class UpdateSubnet(tables.LinkAction):
+ name = "update"
+ verbose_name = _("Edit Subnet")
+ url = "horizon:admin:networks:editsubnet"
+ classes = ("ajax-modal", "btn-edit")
+
+ def get_link_url(self, subnet):
+ network_id = self.table.kwargs['network_id']
+ return reverse(self.url, args=(network_id, subnet.id))
+
+
+class SubnetsTable(tables.DataTable):
+ name = tables.Column("name", verbose_name=_("Name"),
+ link='horizon:admin:networks:subnets:detail')
+ cidr = tables.Column("cidr", verbose_name=_("CIDR"))
+ ip_version = tables.Column("ipver_str", verbose_name=_("IP Version"))
+ gateway_ip = tables.Column("gateway_ip", verbose_name=_("Gateway IP"))
+
+ def get_object_display(self, subnet):
+ return subnet.id
+
+ class Meta:
+ name = "subnets"
+ verbose_name = _("Subnets")
+ table_actions = (CreateSubnet, DeleteSubnet)
+ row_actions = (UpdateSubnet, DeleteSubnet,)
diff --git a/openstack_dashboard/dashboards/admin/networks/subnets/urls.py b/openstack_dashboard/dashboards/admin/networks/subnets/urls.py
new file mode 100644
index 000000000..6af5d626c
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/subnets/urls.py
@@ -0,0 +1,29 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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.defaults import patterns, url
+
+from openstack_dashboard.dashboards.project.networks.subnets.views import \
+ DetailView
+
+
+SUBNETS = r'^(?P<subnet_id>[^/]+)/%s$'
+VIEW_MOD = 'openstack_dashboard.dashboards.admin.networks.subnets.views'
+
+
+urlpatterns = patterns(VIEW_MOD,
+ url(SUBNETS % 'detail', DetailView.as_view(), name='detail')
+)
diff --git a/openstack_dashboard/dashboards/admin/networks/subnets/views.py b/openstack_dashboard/dashboards/admin/networks/subnets/views.py
new file mode 100644
index 000000000..86837cfac
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/subnets/views.py
@@ -0,0 +1,103 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+
+from openstack_dashboard import api
+from .forms import CreateSubnet, UpdateSubnet
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateView(forms.ModalFormView):
+ form_class = CreateSubnet
+ template_name = 'admin/networks/subnets/create.html'
+ success_url = 'horizon:admin:networks:detail'
+
+ def get_success_url(self):
+ return reverse(self.success_url,
+ args=(self.kwargs['network_id'],))
+
+ def get_object(self):
+ if not hasattr(self, "_object"):
+ try:
+ network_id = self.kwargs["network_id"]
+ self._object = api.quantum.network_get(self.request,
+ network_id)
+ except:
+ redirect = reverse('horizon:project:networks:index')
+ msg = _("Unable to retrieve network.")
+ exceptions.handle(self.request, msg, redirect=redirect)
+ return self._object
+
+ def get_context_data(self, **kwargs):
+ context = super(CreateView, self).get_context_data(**kwargs)
+ context['network'] = self.get_object()
+ return context
+
+ def get_initial(self):
+ network = self.get_object()
+ return {"network_id": self.kwargs['network_id'],
+ "network_name": network.name}
+
+
+class UpdateView(forms.ModalFormView):
+ form_class = UpdateSubnet
+ template_name = 'admin/networks/subnets/update.html'
+ context_object_name = 'subnet'
+ success_url = 'horizon:admin:networks:detail'
+
+ def get_success_url(self):
+ return reverse(self.success_url,
+ args=(self.kwargs['network_id'],))
+
+ def _get_object(self, *args, **kwargs):
+ if not hasattr(self, "_object"):
+ subnet_id = self.kwargs['subnet_id']
+ try:
+ self._object = api.quantum.subnet_get(self.request, subnet_id)
+ except:
+ redirect = reverse("horizon:admin:networks:detail",
+ args=(self.kwargs['network_id'],))
+ msg = _('Unable to retrieve subnet details')
+ exceptions.handle(self.request, msg, redirect=redirect)
+ return self._object
+
+ def get_context_data(self, **kwargs):
+ context = super(UpdateView, self).get_context_data(**kwargs)
+ subnet = self._get_object()
+ context['subnet_id'] = subnet['id']
+ context['network_id'] = subnet['network_id']
+ context['cidr'] = subnet['cidr']
+ context['ip_version'] = {4: 'IPv4', 6: 'IPv6'}[subnet['ip_version']]
+ return context
+
+ def get_initial(self):
+ subnet = self._get_object()
+ return {'network_id': self.kwargs['network_id'],
+ 'subnet_id': subnet['id'],
+ 'tenant_id': subnet['tenant_id'],
+ 'cidr': subnet['cidr'],
+ 'ip_version': subnet['ip_version'],
+ 'name': subnet['name'],
+ 'gateway_ip': subnet['gateway_ip']}
diff --git a/openstack_dashboard/dashboards/admin/networks/tables.py b/openstack_dashboard/dashboards/admin/networks/tables.py
new file mode 100644
index 000000000..9f85d714d
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/tables.py
@@ -0,0 +1,82 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.template import defaultfilters as filters
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tables
+
+from openstack_dashboard import api
+from openstack_dashboard.dashboards.project.networks.tables import get_subnets
+
+
+LOG = logging.getLogger(__name__)
+
+
+class DeleteNetwork(tables.DeleteAction):
+ data_type_singular = _("Network")
+ data_type_plural = _("Networks")
+
+ def delete(self, request, obj_id):
+ try:
+ api.quantum.network_delete(request, obj_id)
+ except:
+ msg = _('Failed to delete network %s') % obj_id
+ LOG.info(msg)
+ redirect = reverse('horizon:admin:networks:index')
+ exceptions.handle(request, msg, redirect=redirect)
+
+
+class CreateNetwork(tables.LinkAction):
+ name = "create"
+ verbose_name = _("Create Network")
+ url = "horizon:admin:networks:create"
+ classes = ("ajax-modal", "btn-create")
+
+
+class EditNetwork(tables.LinkAction):
+ name = "update"
+ verbose_name = _("Edit Network")
+ url = "horizon:admin:networks:update"
+ classes = ("ajax-modal", "btn-edit")
+
+
+#def _get_subnets(network):
+# cidrs = [subnet.get('cidr') for subnet in network.subnets]
+# return ','.join(cidrs)
+
+
+class NetworksTable(tables.DataTable):
+ tenant = tables.Column("tenant_name", verbose_name=_("Project"))
+ name = tables.Column("name", verbose_name=_("Network Name"),
+ link='horizon:admin:networks:detail')
+ subnets = tables.Column(get_subnets,
+ verbose_name=_("Subnets Associated"),)
+ shared = tables.Column("shared", verbose_name=_("Shared"),
+ filters=(filters.yesno, filters.capfirst))
+ status = tables.Column("status", verbose_name=_("Status"))
+ admin_state = tables.Column("admin_state",
+ verbose_name=_("Admin State"))
+
+ class Meta:
+ name = "networks"
+ verbose_name = _("Networks")
+ table_actions = (CreateNetwork, DeleteNetwork)
+ row_actions = (EditNetwork, DeleteNetwork)
diff --git a/openstack_dashboard/dashboards/admin/networks/templates/networks/_create.html b/openstack_dashboard/dashboards/admin/networks/templates/networks/_create.html
new file mode 100644
index 000000000..6fda0ca63
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/templates/networks/_create.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}create_network_form{% endblock %}
+{% block form_action %}{% url horizon:admin:networks:create %}{% endblock %}
+
+{% block modal_id %}create_network_modal{% endblock %}
+{% block modal-header %}{% trans "Create Network" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "Select a name for your network."%}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Network" %}" />
+ <a href="{% url horizon:admin:networks:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/networks/templates/networks/_update.html b/openstack_dashboard/dashboards/admin/networks/templates/networks/_update.html
new file mode 100644
index 000000000..7ad0c69c3
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/templates/networks/_update.html
@@ -0,0 +1,24 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}update_network_form{% endblock %}
+{% block form_action %}{% url horizon:admin:networks:update network_id %}{% endblock %}
+
+{% block modal-header %}{% trans "Edit Network" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description:" %}</h3>
+ <p>{% trans "You may update the editable properties of your network here." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Save Changes" %}" />
+ <a href="{% url horizon:admin:networks:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/networks/templates/networks/create.html b/openstack_dashboard/dashboards/admin/networks/templates/networks/create.html
new file mode 100644
index 000000000..975227f4e
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/templates/networks/create.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Create Network" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Create Network") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include "admin/networks/_create.html" %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/networks/templates/networks/index.html b/openstack_dashboard/dashboards/admin/networks/templates/networks/index.html
new file mode 100644
index 000000000..bcb1b74f8
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/templates/networks/index.html
@@ -0,0 +1,21 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Networks" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Networks") %}
+{% endblock page_header %}
+
+{% block main %}
+ <div id="networks">
+ {{ networks_table.render }}
+ </div>
+
+ <div id="subnets">
+ {{ subnets_table.render }}
+ </div>
+
+ <div id="ports">
+ {{ ports_table.render }}
+ </div>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/_create.html b/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/_create.html
new file mode 100644
index 000000000..a35266149
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/_create.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}create_port_form{% endblock %}
+{% block form_action %}{% url horizon:admin:networks:addport network.id %}
+{% endblock %}
+
+{% block modal-header %}{% trans "Create Port" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "You can create a port for the network. If you specify device ID to be attached, the device specified will be attached to the port created."%}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Port" %}" />
+ <a href="{% url horizon:admin:networks:detail network.id %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/_update.html b/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/_update.html
new file mode 100644
index 000000000..bb3162817
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/_update.html
@@ -0,0 +1,29 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}update_port_form{% endblock %}
+{% block form_action %}{% url horizon:admin:networks:editport network_id port_id %}{% endblock %}
+
+{% block modal-header %}{% trans "Edit Port" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <dl>
+ <dt>{% trans "ID" %}</dt>
+ <dd>{{ port_id }}</dd>
+ </dl>
+ <hr>
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description:" %}</h3>
+ <p>{% trans "You may update the editable properties of your port here." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Save Changes" %}" />
+ <a href="{% url horizon:admin:networks:detail network_id %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/create.html b/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/create.html
new file mode 100644
index 000000000..e99551300
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/create.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Create Port" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Create Port") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include "admin/networks/ports/_create.html" %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/update.html b/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/update.html
new file mode 100644
index 000000000..ae0f91cfa
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/templates/networks/ports/update.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Update Port" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Update Port") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'admin/networks/ports/_update.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/_create.html b/openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/_create.html
new file mode 100644
index 000000000..c7367b4c8
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/_create.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}create_subnet_form{% endblock %}
+{% block form_action %}{% url horizon:admin:networks:addsubnet network.id %}
+{% endblock %}
+
+{% block modal-header %}{% trans "Create Subnet" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "You can create a subnet for the network. Any network address can be specified unless the network address does not overlap other subnets in the network." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Subnet" %}" />
+ <a href="{% url horizon:admin:networks:detail network.id %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/_update.html b/openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/_update.html
new file mode 100644
index 000000000..45a125ea6
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/_update.html
@@ -0,0 +1,33 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}update_subnet_form{% endblock %}
+{% block form_action %}{% url horizon:admin:networks:editsubnet network_id subnet_id %}{% endblock %}
+
+{% block modal-header %}{% trans "Edit Subnet" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <dl>
+ <dt>{% trans "ID" %}</dt>
+ <dd>{{ subnet_id }}</dd>
+ <dt>{% trans "Network Address" %}</dt>
+ <dd>{{ cidr }}</dd>
+ <dt>{% trans "IP version" %}</dt>
+ <dd>{{ ip_version }}</dd>
+ </dl>
+ <hr>
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description:" %}</h3>
+ <p>{% trans "You may update the editable properties of your subnet here." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Save Changes" %}" />
+ <a href="{% url horizon:admin:networks:detail network_id %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/create.html b/openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/create.html
new file mode 100644
index 000000000..84624cc13
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/create.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Create Subnet" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Create Subnet") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include "admin/networks/subnets/_create.html" %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/index.html b/openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/index.html
new file mode 100644
index 000000000..9c25d565e
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/index.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Network Detail" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Network Detail") %}
+{% endblock page_header %}
+
+{% block main %}
+ {{ table.render }}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/update.html b/openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/update.html
new file mode 100644
index 000000000..b152cdf4e
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/templates/networks/subnets/update.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Update Subnet" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Update Subnet") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'admin/networks/subnets/_update.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/networks/templates/networks/update.html b/openstack_dashboard/dashboards/admin/networks/templates/networks/update.html
new file mode 100644
index 000000000..a70a0b1a7
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/templates/networks/update.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Update Network" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Update Network") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'admin/networks/_update.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/networks/tests.py b/openstack_dashboard/dashboards/admin/networks/tests.py
new file mode 100644
index 000000000..4ea208cae
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/tests.py
@@ -0,0 +1,805 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 import http
+from django.core.urlresolvers import reverse
+
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+INDEX_URL = reverse('horizon:admin:networks:index')
+
+
+class NetworkTests(test.BaseAdminViewTests):
+ @test.create_stubs({api.quantum: ('network_list',),
+ api.keystone: ('tenant_list',)})
+ def test_index(self):
+ tenants = self.tenants.list()
+ api.quantum.network_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.networks.list())
+ api.keystone.tenant_list(IsA(http.HttpRequest), admin=True)\
+ .AndReturn(tenants)
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(INDEX_URL)
+
+ self.assertTemplateUsed(res, 'admin/networks/index.html')
+ networks = res.context['networks_table'].data
+ self.assertItemsEqual(networks, self.networks.list())
+
+ @test.create_stubs({api.quantum: ('network_list',)})
+ def test_index_network_list_exception(self):
+ api.quantum.network_list(IsA(http.HttpRequest)) \
+ .AndRaise(self.exceptions.quantum)
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(INDEX_URL)
+
+ self.assertTemplateUsed(res, 'admin/networks/index.html')
+ self.assertEqual(len(res.context['networks_table'].data), 0)
+ self.assertMessageCount(res, error=1)
+
+ @test.create_stubs({api.quantum: ('network_get',
+ 'subnet_list',
+ 'port_list',)})
+ def test_network_detail(self):
+ network_id = self.networks.first().id
+ api.quantum.network_get(IsA(http.HttpRequest), network_id)\
+ .AndReturn(self.networks.first())
+ api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.subnets.first()])
+ api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.ports.first()])
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:admin:networks:detail',
+ args=[network_id]))
+
+ self.assertTemplateUsed(res, 'project/networks/detail.html')
+ subnets = res.context['subnets_table'].data
+ ports = res.context['ports_table'].data
+ self.assertItemsEqual(subnets, [self.subnets.first()])
+ self.assertItemsEqual(ports, [self.ports.first()])
+
+ @test.create_stubs({api.quantum: ('network_get',
+ 'subnet_list',
+ 'port_list',)})
+ def test_network_detail_network_exception(self):
+ network_id = self.networks.first().id
+ api.quantum.network_get(IsA(http.HttpRequest), network_id)\
+ .AndRaise(self.exceptions.quantum)
+ api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.subnets.first()])
+ api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.ports.first()])
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:networks:detail', args=[network_id])
+ res = self.client.get(url)
+
+ redir_url = INDEX_URL
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('network_get',
+ 'subnet_list',
+ 'port_list',)})
+ def test_network_detail_subnet_exception(self):
+ network_id = self.networks.first().id
+ api.quantum.network_get(IsA(http.HttpRequest), network_id).\
+ AndReturn(self.networks.first())
+ api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id).\
+ AndRaise(self.exceptions.quantum)
+ api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id).\
+ AndReturn([self.ports.first()])
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:admin:networks:detail',
+ args=[network_id]))
+
+ self.assertTemplateUsed(res, 'project/networks/detail.html')
+ subnets = res.context['subnets_table'].data
+ ports = res.context['ports_table'].data
+ self.assertEqual(len(subnets), 0)
+ self.assertItemsEqual(ports, [self.ports.first()])
+
+ @test.create_stubs({api.quantum: ('network_get',
+ 'subnet_list',
+ 'port_list',)})
+ def test_network_detail_port_exception(self):
+ network_id = self.networks.first().id
+ api.quantum.network_get(IsA(http.HttpRequest), network_id).\
+ AndReturn(self.networks.first())
+ api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id).\
+ AndReturn([self.subnets.first()])
+ api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id).\
+ AndRaise(self.exceptions.quantum)
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:admin:networks:detail',
+ args=[network_id]))
+
+ self.assertTemplateUsed(res, 'project/networks/detail.html')
+ subnets = res.context['subnets_table'].data
+ ports = res.context['ports_table'].data
+ self.assertItemsEqual(subnets, [self.subnets.first()])
+ self.assertEqual(len(ports), 0)
+
+ @test.create_stubs({api.keystone: ('tenant_list',)})
+ def test_network_create_get(self):
+ tenants = self.tenants.list()
+ api.keystone.tenant_list(IsA(http.HttpRequest), admin=True)\
+ .AndReturn(tenants)
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:networks:create')
+ res = self.client.get(url)
+
+ self.assertTemplateUsed(res, 'admin/networks/create.html')
+
+ @test.create_stubs({api.quantum: ('network_create',),
+ api.keystone: ('tenant_list',)})
+ def test_network_create_post(self):
+ tenants = self.tenants.list()
+ tenant_id = self.tenants.first().id
+ network = self.networks.first()
+ api.keystone.tenant_list(IsA(http.HttpRequest), admin=True)\
+ .AndReturn(tenants)
+ api.quantum.network_create(IsA(http.HttpRequest), name=network.name,
+ tenant_id=tenant_id, shared=True)\
+ .AndReturn(network)
+ self.mox.ReplayAll()
+
+ form_data = {'tenant_id': tenant_id,
+ 'name': network.name,
+ 'shared': True}
+ url = reverse('horizon:admin:networks:create')
+ res = self.client.post(url, form_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('network_create',),
+ api.keystone: ('tenant_list',)})
+ def test_network_create_post_network_exception(self):
+ tenants = self.tenants.list()
+ tenant_id = self.tenants.first().id
+ network = self.networks.first()
+ api.keystone.tenant_list(IsA(http.HttpRequest), admin=True)\
+ .AndReturn(tenants)
+ api.quantum.network_create(IsA(http.HttpRequest), name=network.name,
+ tenant_id=tenant_id, shared=False)\
+ .AndRaise(self.exceptions.quantum)
+ self.mox.ReplayAll()
+
+ form_data = {'tenant_id': tenant_id,
+ 'name': network.name,
+ 'shared': False}
+ url = reverse('horizon:admin:networks:create')
+ res = self.client.post(url, form_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('network_get',)})
+ def test_network_update_get(self):
+ network = self.networks.first()
+ api.quantum.network_get(IsA(http.HttpRequest), network.id)\
+ .AndReturn(network)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:networks:update', args=[network.id])
+ res = self.client.get(url)
+
+ self.assertTemplateUsed(res, 'admin/networks/update.html')
+
+ @test.create_stubs({api.quantum: ('network_get',)})
+ def test_network_update_get_exception(self):
+ network = self.networks.first()
+ api.quantum.network_get(IsA(http.HttpRequest), network.id)\
+ .AndRaise(self.exceptions.quantum)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:networks:update', args=[network.id])
+ res = self.client.get(url)
+
+ redir_url = INDEX_URL
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('network_modify',
+ 'network_get',)})
+ def test_network_update_post(self):
+ network = self.networks.first()
+ api.quantum.network_modify(IsA(http.HttpRequest), network.id,
+ name=network.name, shared=True)\
+ .AndReturn(network)
+ api.quantum.network_get(IsA(http.HttpRequest), network.id)\
+ .AndReturn(network)
+ self.mox.ReplayAll()
+
+ formData = {'network_id': network.id,
+ 'name': network.name,
+ 'tenant_id': network.tenant_id,
+ 'shared': True}
+ url = reverse('horizon:admin:networks:update', args=[network.id])
+ res = self.client.post(url, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('network_modify',
+ 'network_get',)})
+ def test_network_update_post_exception(self):
+ network = self.networks.first()
+ api.quantum.network_modify(IsA(http.HttpRequest), network.id,
+ name=network.name, shared=False)\
+ .AndRaise(self.exceptions.quantum)
+ api.quantum.network_get(IsA(http.HttpRequest), network.id)\
+ .AndReturn(network)
+ self.mox.ReplayAll()
+
+ form_data = {'network_id': network.id,
+ 'name': network.name,
+ 'tenant_id': network.tenant_id,
+ 'shared': False}
+ url = reverse('horizon:admin:networks:update', args=[network.id])
+ res = self.client.post(url, form_data)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('network_list',
+ 'network_delete'),
+ api.keystone: ('tenant_list',)})
+ def test_delete_network(self):
+ tenants = self.tenants.list()
+ network = self.networks.first()
+ api.keystone.tenant_list(IsA(http.HttpRequest), admin=True)\
+ .AndReturn(tenants)
+ api.quantum.network_list(IsA(http.HttpRequest))\
+ .AndReturn([network])
+ api.quantum.network_delete(IsA(http.HttpRequest), network.id)
+
+ self.mox.ReplayAll()
+
+ form_data = {'action': 'networks__delete__%s' % network.id}
+ res = self.client.post(INDEX_URL, form_data)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('network_list',
+ 'network_delete'),
+ api.keystone: ('tenant_list',)})
+ def test_delete_network_exception(self):
+ tenants = self.tenants.list()
+ network = self.networks.first()
+ api.keystone.tenant_list(IsA(http.HttpRequest), admin=True)\
+ .AndReturn(tenants)
+ api.quantum.network_list(IsA(http.HttpRequest))\
+ .AndReturn([network])
+ api.quantum.network_delete(IsA(http.HttpRequest), network.id)\
+ .AndRaise(self.exceptions.quantum)
+
+ self.mox.ReplayAll()
+
+ form_data = {'action': 'networks__delete__%s' % network.id}
+ res = self.client.post(INDEX_URL, form_data)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('subnet_get',)})
+ def test_subnet_detail(self):
+ subnet = self.subnets.first()
+ api.quantum.subnet_get(IsA(http.HttpRequest), subnet.id)\
+ .AndReturn(self.subnets.first())
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:networks:subnets:detail',
+ args=[subnet.id])
+ res = self.client.get(url)
+
+ self.assertTemplateUsed(res, 'project/networks/subnets/detail.html')
+ self.assertEqual(res.context['subnet'].id, subnet.id)
+
+ @test.create_stubs({api.quantum: ('subnet_get',)})
+ def test_subnet_detail_exception(self):
+ subnet = self.subnets.first()
+ api.quantum.subnet_get(IsA(http.HttpRequest), subnet.id)\
+ .AndRaise(self.exceptions.quantum)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:networks:subnets:detail',
+ args=[subnet.id])
+ res = self.client.get(url)
+
+ # admin DetailView is shared with userpanel one, so
+ # redirection URL on error is userpanel index.
+ redir_url = reverse('horizon:project:networks:index')
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('network_get',)})
+ def test_subnet_create_get(self):
+ network = self.networks.first()
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:networks:addsubnet',
+ args=[network.id])
+ res = self.client.get(url)
+
+ self.assertTemplateUsed(res, 'admin/networks/subnets/create.html')
+
+ @test.create_stubs({api.quantum: ('network_get',
+ 'subnet_create',)})
+ def test_subnet_create_post(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ api.quantum.subnet_create(IsA(http.HttpRequest),
+ network_id=network.id,
+ network_name=network.name,
+ name=subnet.name,
+ cidr=subnet.cidr,
+ ip_version=subnet.ip_version,
+ gateway_ip=subnet.gateway_ip,
+ tenant_id=subnet.tenant_id)\
+ .AndReturn(subnet)
+ self.mox.ReplayAll()
+
+ form_data = {'network_id': subnet.network_id,
+ 'network_name': network.name,
+ 'name': subnet.name,
+ 'cidr': subnet.cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': subnet.gateway_ip}
+ url = reverse('horizon:admin:networks:addsubnet',
+ args=[subnet.network_id])
+ res = self.client.post(url, form_data)
+
+ self.assertNoFormErrors(res)
+ redir_url = reverse('horizon:admin:networks:detail',
+ args=[subnet.network_id])
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('network_get',
+ 'subnet_create',)})
+ def test_subnet_create_post_network_exception(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndRaise(self.exceptions.quantum)
+ self.mox.ReplayAll()
+
+ form_data = {'network_id': subnet.network_id,
+ 'network_name': network.name,
+ 'name': subnet.name,
+ 'cidr': subnet.cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': subnet.gateway_ip}
+ url = reverse('horizon:admin:networks:addsubnet',
+ args=[subnet.network_id])
+ res = self.client.post(url, form_data)
+
+ self.assertNoFormErrors(res)
+ # admin DetailView is shared with userpanel one, so
+ # redirection URL on error is userpanel index.
+ redir_url = reverse('horizon:project:networks:index')
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('network_get',
+ 'subnet_create',)})
+ def test_subnet_create_post_subnet_exception(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ api.quantum.subnet_create(IsA(http.HttpRequest),
+ network_id=network.id,
+ network_name=network.name,
+ name=subnet.name,
+ cidr=subnet.cidr,
+ ip_version=subnet.ip_version,
+ gateway_ip=subnet.gateway_ip,
+ tenant_id=subnet.tenant_id)\
+ .AndRaise(self.exceptions.quantum)
+ self.mox.ReplayAll()
+
+ form_data = {'network_id': subnet.network_id,
+ 'network_name': network.name,
+ 'name': subnet.name,
+ 'cidr': subnet.cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': subnet.gateway_ip}
+ url = reverse('horizon:admin:networks:addsubnet',
+ args=[subnet.network_id])
+ res = self.client.post(url, form_data)
+
+ redir_url = reverse('horizon:admin:networks:detail',
+ args=[subnet.network_id])
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('network_get',)})
+ def test_subnet_create_post_cidr_inconsistent(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ self.mox.ReplayAll()
+
+ # dummy IPv6 address
+ cidr = '2001:0DB8:0:CD30:123:4567:89AB:CDEF/60'
+ form_data = {'network_id': subnet.network_id,
+ 'network_name': network.name,
+ 'name': subnet.name,
+ 'cidr': cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': subnet.gateway_ip}
+ url = reverse('horizon:admin:networks:addsubnet',
+ args=[subnet.network_id])
+ res = self.client.post(url, form_data)
+
+ expected_msg = 'Network Address and IP version are inconsistent.'
+ self.assertContains(res, expected_msg)
+
+ @test.create_stubs({api.quantum: ('network_get',)})
+ def test_subnet_create_post_gw_inconsistent(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ self.mox.ReplayAll()
+
+ # dummy IPv6 address
+ gateway_ip = '2001:0DB8:0:CD30:123:4567:89AB:CDEF'
+ form_data = {'network_id': subnet.network_id,
+ 'network_name': network.name,
+ 'name': subnet.name,
+ 'cidr': subnet.cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': gateway_ip}
+ url = reverse('horizon:admin:networks:addsubnet',
+ args=[subnet.network_id])
+ res = self.client.post(url, form_data)
+
+ self.assertContains(res, 'Gateway IP and IP version are inconsistent.')
+
+ @test.create_stubs({api.quantum: ('subnet_modify',
+ 'subnet_get',)})
+ def test_subnet_update_post(self):
+ subnet = self.subnets.first()
+ api.quantum.subnet_get(IsA(http.HttpRequest), subnet.id)\
+ .AndReturn(subnet)
+ api.quantum.subnet_modify(IsA(http.HttpRequest), subnet.id,
+ name=subnet.name,
+ gateway_ip=subnet.gateway_ip)\
+ .AndReturn(subnet)
+ self.mox.ReplayAll()
+
+ formData = {'network_id': subnet.network_id,
+ 'tenant_id': subnet.tenant_id,
+ 'subnet_id': subnet.id,
+ 'name': subnet.name,
+ 'cidr': subnet.cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': subnet.gateway_ip}
+ url = reverse('horizon:admin:networks:editsubnet',
+ args=[subnet.network_id, subnet.id])
+ res = self.client.post(url, formData)
+
+ redir_url = reverse('horizon:admin:networks:detail',
+ args=[subnet.network_id])
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('subnet_modify',
+ 'subnet_get',)})
+ def test_subnet_update_post_gw_inconsistent(self):
+ subnet = self.subnets.first()
+ api.quantum.subnet_get(IsA(http.HttpRequest), subnet.id)\
+ .AndReturn(subnet)
+ self.mox.ReplayAll()
+
+ # dummy IPv6 address
+ gateway_ip = '2001:0DB8:0:CD30:123:4567:89AB:CDEF'
+ formData = {'network_id': subnet.network_id,
+ 'tenant_id': subnet.tenant_id,
+ 'subnet_id': subnet.id,
+ 'name': subnet.name,
+ 'cidr': subnet.cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': gateway_ip}
+ url = reverse('horizon:admin:networks:editsubnet',
+ args=[subnet.network_id, subnet.id])
+ res = self.client.post(url, formData)
+
+ self.assertContains(res, 'Gateway IP and IP version are inconsistent.')
+
+ @test.create_stubs({api.quantum: ('subnet_delete',
+ 'subnet_list',
+ 'port_list',)})
+ def test_subnet_delete(self):
+ subnet = self.subnets.first()
+ network_id = subnet.network_id
+ api.quantum.subnet_delete(IsA(http.HttpRequest), subnet.id)
+ api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.subnets.first()])
+ api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.ports.first()])
+ self.mox.ReplayAll()
+
+ formData = {'action': 'subnets__delete__%s' % subnet.id}
+ url = reverse('horizon:admin:networks:detail',
+ args=[network_id])
+ res = self.client.post(url, formData)
+
+ self.assertRedirectsNoFollow(res, url)
+
+ @test.create_stubs({api.quantum: ('subnet_delete',
+ 'subnet_list',
+ 'port_list',)})
+ def test_subnet_delete_exception(self):
+ subnet = self.subnets.first()
+ network_id = subnet.network_id
+ api.quantum.subnet_delete(IsA(http.HttpRequest), subnet.id)\
+ .AndRaise(self.exceptions.quantum)
+ api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.subnets.first()])
+ api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.ports.first()])
+ self.mox.ReplayAll()
+
+ formData = {'action': 'subnets__delete__%s' % subnet.id}
+ url = reverse('horizon:admin:networks:detail',
+ args=[network_id])
+ res = self.client.post(url, formData)
+
+ self.assertRedirectsNoFollow(res, url)
+
+ @test.create_stubs({api.quantum: ('port_get',)})
+ def test_port_detail(self):
+ port = self.ports.first()
+ api.quantum.port_get(IsA(http.HttpRequest), port.id)\
+ .AndReturn(self.ports.first())
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:admin:networks:ports:detail',
+ args=[port.id]))
+
+ self.assertTemplateUsed(res, 'project/networks/ports/detail.html')
+ self.assertEqual(res.context['port'].id, port.id)
+
+ @test.create_stubs({api.quantum: ('port_get',)})
+ def test_port_detail_exception(self):
+ port = self.ports.first()
+ api.quantum.port_get(IsA(http.HttpRequest), port.id)\
+ .AndRaise(self.exceptions.quantum)
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:admin:networks:ports:detail',
+ args=[port.id]))
+
+ # admin DetailView is shared with userpanel one, so
+ # redirection URL on error is userpanel index.
+ redir_url = reverse('horizon:project:networks:index')
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('network_get',)})
+ def test_port_create_get(self):
+ network = self.networks.first()
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:networks:addport',
+ args=[network.id])
+ res = self.client.get(url)
+
+ self.assertTemplateUsed(res, 'admin/networks/ports/create.html')
+
+ @test.create_stubs({api.quantum: ('network_get',
+ 'port_create')})
+ def test_port_create_post(self):
+ network = self.networks.first()
+ port = self.ports.first()
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ api.quantum.port_create(IsA(http.HttpRequest),
+ tenant_id=network.tenant_id,
+ network_id=network.id,
+ network_name=network.name,
+ name=port.name,
+ device_id=port.device_id)\
+ .AndReturn(port)
+ self.mox.ReplayAll()
+
+ form_data = {'network_id': port.network_id,
+ 'network_name': network.name,
+ 'name': port.name,
+ 'device_id': port.device_id}
+ url = reverse('horizon:admin:networks:addport',
+ args=[port.network_id])
+ res = self.client.post(url, form_data)
+
+ self.assertNoFormErrors(res)
+ redir_url = reverse('horizon:admin:networks:detail',
+ args=[port.network_id])
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('network_get',
+ 'port_create')})
+ def test_port_create_post_exception(self):
+ network = self.networks.first()
+ port = self.ports.first()
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ api.quantum.port_create(IsA(http.HttpRequest),
+ tenant_id=network.tenant_id,
+ network_id=network.id,
+ network_name=network.name,
+ name=port.name,
+ device_id=port.device_id)\
+ .AndRaise(self.exceptions.quantum)
+ self.mox.ReplayAll()
+
+ form_data = {'network_id': port.network_id,
+ 'network_name': network.name,
+ 'name': port.name,
+ 'device_id': port.device_id}
+ url = reverse('horizon:admin:networks:addport',
+ args=[port.network_id])
+ res = self.client.post(url, form_data)
+
+ self.assertNoFormErrors(res)
+ redir_url = reverse('horizon:admin:networks:detail',
+ args=[port.network_id])
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('port_get',)})
+ def test_port_update_get(self):
+ port = self.ports.first()
+ api.quantum.port_get(IsA(http.HttpRequest),
+ port.id)\
+ .AndReturn(port)
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:networks:editport',
+ args=[port.network_id, port.id])
+ res = self.client.get(url)
+
+ self.assertTemplateUsed(res, 'admin/networks/ports/update.html')
+
+ @test.create_stubs({api.quantum: ('port_get',
+ 'port_modify')})
+ def test_port_update_post(self):
+ port = self.ports.first()
+ api.quantum.port_get(IsA(http.HttpRequest), port.id)\
+ .AndReturn(port)
+ api.quantum.port_modify(IsA(http.HttpRequest), port.id,
+ name=port.name, device_id=port.device_id)\
+ .AndReturn(port)
+ self.mox.ReplayAll()
+
+ formData = {'tenant_id': port.tenant_id,
+ 'network_id': port.network_id,
+ 'port_id': port.id,
+ 'name': port.name,
+ 'device_id': port.device_id}
+ url = reverse('horizon:admin:networks:editport',
+ args=[port.network_id, port.id])
+ res = self.client.post(url, formData)
+
+ redir_url = reverse('horizon:admin:networks:detail',
+ args=[port.network_id])
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('port_get',
+ 'port_modify')})
+ def test_port_update_post_exception(self):
+ port = self.ports.first()
+ api.quantum.port_get(IsA(http.HttpRequest), port.id)\
+ .AndReturn(port)
+ api.quantum.port_modify(IsA(http.HttpRequest), port.id,
+ name=port.name, device_id=port.device_id)\
+ .AndRaise(self.exceptions.quantum)
+ self.mox.ReplayAll()
+
+ formData = {'tenant_id': port.tenant_id,
+ 'network_id': port.network_id,
+ 'port_id': port.id,
+ 'name': port.name,
+ 'device_id': port.device_id}
+ url = reverse('horizon:admin:networks:editport',
+ args=[port.network_id, port.id])
+ res = self.client.post(url, formData)
+
+ redir_url = reverse('horizon:admin:networks:detail',
+ args=[port.network_id])
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('port_delete',
+ 'subnet_list',
+ 'port_list',)})
+ def test_port_delete(self):
+ port = self.ports.first()
+ network_id = port.network_id
+ api.quantum.port_delete(IsA(http.HttpRequest), port.id)
+ api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.subnets.first()])
+ api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.ports.first()])
+ self.mox.ReplayAll()
+
+ formData = {'action': 'ports__delete__%s' % port.id}
+ url = reverse('horizon:admin:networks:detail',
+ args=[network_id])
+ res = self.client.post(url, formData)
+
+ self.assertRedirectsNoFollow(res, url)
+
+ @test.create_stubs({api.quantum: ('port_delete',
+ 'subnet_list',
+ 'port_list',)})
+ def test_port_delete_exception(self):
+ port = self.ports.first()
+ network_id = port.network_id
+ api.quantum.port_delete(IsA(http.HttpRequest), port.id)\
+ .AndRaise(self.exceptions.quantum)
+ api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.subnets.first()])
+ api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.ports.first()])
+ self.mox.ReplayAll()
+
+ formData = {'action': 'ports__delete__%s' % port.id}
+ url = reverse('horizon:admin:networks:detail',
+ args=[network_id])
+ res = self.client.post(url, formData)
+
+ self.assertRedirectsNoFollow(res, url)
diff --git a/openstack_dashboard/dashboards/admin/networks/urls.py b/openstack_dashboard/dashboards/admin/networks/urls.py
new file mode 100644
index 000000000..59387d886
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/urls.py
@@ -0,0 +1,47 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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.defaults import patterns, url, include
+from .views import IndexView, CreateView, DetailView, UpdateView
+
+from .subnets.views import CreateView as AddSubnetView
+from .subnets.views import UpdateView as EditSubnetView
+from .ports.views import CreateView as AddPortView
+from .ports.views import UpdateView as EditPortView
+
+from .subnets import urls as subnet_urls
+from .ports import urls as port_urls
+
+
+NETWORKS = r'^(?P<network_id>[^/]+)/%s$'
+
+
+urlpatterns = patterns('',
+ url(r'^$', IndexView.as_view(), name='index'),
+ url(r'^create/$', CreateView.as_view(), name='create'),
+ url(NETWORKS % 'update', UpdateView.as_view(), name='update'),
+ # for detail view
+ url(NETWORKS % 'detail', DetailView.as_view(), name='detail'),
+ url(NETWORKS % 'subnets/create', AddSubnetView.as_view(),
+ name='addsubnet'),
+ url(NETWORKS % 'ports/create', AddPortView.as_view(), name='addport'),
+ url(r'^(?P<network_id>[^/]+)/subnets/(?P<subnet_id>[^/]+)/update$',
+ EditSubnetView.as_view(), name='editsubnet'),
+ url(r'^(?P<network_id>[^/]+)/ports/(?P<port_id>[^/]+)/update$',
+ EditPortView.as_view(), name='editport'),
+
+ url(r'^subnets/', include(subnet_urls, namespace='subnets')),
+ url(r'^ports/', include(port_urls, namespace='ports')))
diff --git a/openstack_dashboard/dashboards/admin/networks/views.py b/openstack_dashboard/dashboards/admin/networks/views.py
new file mode 100644
index 000000000..2c38adb8e
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/networks/views.py
@@ -0,0 +1,140 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse_lazy
+from django.utils.translation import ugettext_lazy as _
+from django.utils.datastructures import SortedDict
+
+from horizon import exceptions
+from horizon import forms
+from horizon import tables
+
+from openstack_dashboard import api
+from openstack_dashboard.dashboards.project.networks import views as user_views
+from .tables import NetworksTable
+from .subnets.tables import SubnetsTable
+from .ports.tables import PortsTable
+from .forms import CreateNetwork, UpdateNetwork
+
+
+LOG = logging.getLogger(__name__)
+
+
+class IndexView(tables.DataTableView):
+ table_class = NetworksTable
+ template_name = 'admin/networks/index.html'
+
+ def _get_tenant_list(self):
+ if not hasattr(self, "_tenants"):
+ try:
+ tenants = api.keystone.tenant_list(self.request, admin=True)
+ except:
+ tenants = []
+ msg = _('Unable to retrieve instance tenant information.')
+ exceptions.handle(self.request, msg)
+
+ tenant_dict = SortedDict([(t.id, t) for t in tenants])
+ self._tenants = tenant_dict
+ return self._tenants
+
+ def get_data(self):
+ try:
+ networks = api.quantum.network_list(self.request)
+ except:
+ networks = []
+ msg = _('Network list can not be retrieved.')
+ exceptions.handle(self.request, msg)
+ if networks:
+ tenant_dict = self._get_tenant_list()
+ for n in networks:
+ # Set tenant name
+ tenant = tenant_dict.get(n.tenant_id, None)
+ n.tenant_name = getattr(tenant, 'name', None)
+ # If name is empty use UUID as name
+ n.set_id_as_name_if_empty()
+ return networks
+
+
+class CreateView(forms.ModalFormView):
+ form_class = CreateNetwork
+ template_name = 'admin/networks/create.html'
+ success_url = reverse_lazy('horizon:admin:networks:index')
+
+
+class DetailView(tables.MultiTableView):
+ table_classes = (SubnetsTable, PortsTable)
+ template_name = 'project/networks/detail.html'
+ failure_url = reverse_lazy('horizon:admin:networks:index')
+
+ def get_subnets_data(self):
+ try:
+ network_id = self.kwargs['network_id']
+ subnets = api.quantum.subnet_list(self.request,
+ network_id=network_id)
+ except:
+ subnets = []
+ msg = _('Subnet list can not be retrieved.')
+ exceptions.handle(self.request, msg)
+ for s in subnets:
+ s.set_id_as_name_if_empty()
+ return subnets
+
+ def get_ports_data(self):
+ try:
+ network_id = self.kwargs['network_id']
+ ports = api.quantum.port_list(self.request, network_id=network_id)
+ except:
+ ports = []
+ msg = _('Port list can not be retrieved.')
+ exceptions.handle(self.request, msg)
+ for p in ports:
+ p.set_id_as_name_if_empty()
+ return ports
+
+ def _get_data(self):
+ if not hasattr(self, "_network"):
+ try:
+ network_id = self.kwargs['network_id']
+ network = api.quantum.network_get(self.request, network_id)
+ network.set_id_as_name_if_empty(length=0)
+ except:
+ redirect = self.failure_url
+ exceptions.handle(self.request,
+ _('Unable to retrieve details for '
+ 'network "%s".') % network_id,
+ redirect=redirect)
+ self._network = network
+ return self._network
+
+ def get_context_data(self, **kwargs):
+ context = super(DetailView, self).get_context_data(**kwargs)
+ context["network"] = self._get_data()
+ return context
+
+
+class UpdateView(user_views.UpdateView):
+ form_class = UpdateNetwork
+ template_name = 'admin/networks/update.html'
+ success_url = reverse_lazy('horizon:admin:networks:index')
+
+ def get_initial(self):
+ network = self._get_object()
+ return {'network_id': network['id'],
+ 'tenant_id': network['tenant_id'],
+ 'name': network['name'],
+ 'shared': network['shared']}
diff --git a/openstack_dashboard/dashboards/admin/overview/__init__.py b/openstack_dashboard/dashboards/admin/overview/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/overview/__init__.py
diff --git a/openstack_dashboard/dashboards/admin/overview/panel.py b/openstack_dashboard/dashboards/admin/overview/panel.py
new file mode 100644
index 000000000..ec2375786
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/overview/panel.py
@@ -0,0 +1,34 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.admin import dashboard
+
+
+class Overview(horizon.Panel):
+ name = _("Overview")
+ slug = 'overview'
+ permissions = ('openstack.roles.admin',)
+
+
+dashboard.Admin.register(Overview)
diff --git a/openstack_dashboard/dashboards/admin/overview/templates/overview/usage.csv b/openstack_dashboard/dashboards/admin/overview/templates/overview/usage.csv
new file mode 100644
index 000000000..57f50b99a
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/overview/templates/overview/usage.csv
@@ -0,0 +1,9 @@
+Usage Report For Period:,{{ usage.start|date:"b. d Y" }},/,{{ usage.end|date:"b. d Y" }}
+Active Instances:,{{ usage.summary.instances }}
+CPU-HRs Used:,{{ usage.summary.vcpu_hours }}
+Total Active RAM (MB):,{{ usage.summary.memory_mb }}
+Total Disk Size:,{{ usage.summary.local_gb }}
+Total Disk Usage:,{{ usage.summary.disk_gb_hours }}
+
+Tenant,VCPUs,RamMB,DiskGB,Usage(Hours)
+{% for u in usage.usage_list %}{{ u.tenant_id|addslashes }},{{ u.vcpus|addslashes }},{{ u.memory_mb|addslashes }},{{ u.local_gb|addslashes }},{{ u.vcpu_hours}}{% endfor %}
diff --git a/openstack_dashboard/dashboards/admin/overview/templates/overview/usage.html b/openstack_dashboard/dashboards/admin/overview/templates/overview/usage.html
new file mode 100644
index 000000000..7f53c2a9d
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/overview/templates/overview/usage.html
@@ -0,0 +1,22 @@
+{% extends 'base.html' %}
+{% load i18n sizeformat %}
+{% block title %}{% trans "Usage Overview" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Overview") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% if monitoring %}
+ <div id="monitoring">
+ <h3>{% trans "Monitoring" %}: </h3>
+ <ul id="external_links">
+ {% for link in monitoring %}
+ <li><a target="_blank" href="{{ link.1 }}">{{ link.0 }}</a></li>
+ {% endfor %}
+ </ul>
+ </div>
+ {% endif %}
+ {% include "horizon/common/_usage_summary.html" %}
+ {{ table.render }}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/overview/tests.py b/openstack_dashboard/dashboards/admin/overview/tests.py
new file mode 100644
index 000000000..bdbce47ef
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/overview/tests.py
@@ -0,0 +1,97 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 datetime
+
+from django import http
+from django.core.urlresolvers import reverse
+from django.utils import timezone
+
+from mox import IsA, Func
+
+from horizon.templatetags.sizeformat import mbformat
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+from openstack_dashboard import usage
+
+
+INDEX_URL = reverse('horizon:project:overview:index')
+
+
+class UsageViewTests(test.BaseAdminViewTests):
+ @test.create_stubs({api: ('usage_list',),
+ api.nova: ('tenant_quota_usages',),
+ api.keystone: ('tenant_list',)})
+ def test_usage(self):
+ now = timezone.now()
+ usage_obj = api.nova.Usage(self.usages.first())
+ quotas = self.quota_usages.first()
+ api.keystone.tenant_list(IsA(http.HttpRequest), admin=True) \
+ .AndReturn(self.tenants.list())
+ api.usage_list(IsA(http.HttpRequest),
+ datetime.datetime(now.year, now.month, 1, 0, 0, 0),
+ Func(usage.almost_now)) \
+ .AndReturn([usage_obj])
+ api.nova.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(quotas)
+ self.mox.ReplayAll()
+ res = self.client.get(reverse('horizon:admin:overview:index'))
+ self.assertTemplateUsed(res, 'admin/overview/usage.html')
+ self.assertTrue(isinstance(res.context['usage'], usage.GlobalUsage))
+ self.assertContains(res,
+ '<td class="sortable normal_column">test_tenant'
+ '</td>'
+ '<td class="sortable normal_column">%s</td>'
+ '<td class="sortable normal_column">%s</td>'
+ '<td class="sortable normal_column">%s</td>'
+ '<td class="sortable normal_column">%.2f</td>'
+ '<td class="sortable normal_column">%.2f</td>' %
+ (usage_obj.vcpus,
+ usage_obj.disk_gb_hours,
+ mbformat(usage_obj.memory_mb),
+ usage_obj.vcpu_hours,
+ usage_obj.total_local_gb_usage))
+
+ @test.create_stubs({api: ('usage_list',),
+ api.nova: ('tenant_quota_usages',),
+ api.keystone: ('tenant_list',)})
+ def test_usage_csv(self):
+ now = timezone.now()
+ usage_obj = api.nova.Usage(self.usages.first())
+ quotas = self.quota_usages.first()
+ api.keystone.tenant_list(IsA(http.HttpRequest), admin=True) \
+ .AndReturn(self.tenants.list())
+ api.usage_list(IsA(http.HttpRequest),
+ datetime.datetime(now.year, now.month, 1, 0, 0, 0),
+ Func(usage.almost_now)) \
+ .AndReturn([usage_obj])
+ api.nova.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(quotas)
+ self.mox.ReplayAll()
+ csv_url = reverse('horizon:admin:overview:index') + "?format=csv"
+ res = self.client.get(csv_url)
+ self.assertTemplateUsed(res, 'admin/overview/usage.csv')
+ self.assertTrue(isinstance(res.context['usage'], usage.GlobalUsage))
+ self.assertContains(res, 'Tenant,VCPUs,RamMB,DiskGB,Usage(Hours)\n'
+ '%s,%s,%s,%s,%f' %
+ (usage_obj.tenant_id,
+ usage_obj.vcpus,
+ usage_obj.memory_mb,
+ usage_obj.disk_gb_hours,
+ usage_obj.vcpu_hours))
diff --git a/openstack_dashboard/dashboards/admin/overview/urls.py b/openstack_dashboard/dashboards/admin/overview/urls.py
new file mode 100644
index 000000000..7aca2a477
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/overview/urls.py
@@ -0,0 +1,29 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import url, patterns
+
+from .views import GlobalOverview
+
+
+urlpatterns = patterns('',
+ url(r'^$', GlobalOverview.as_view(), name='index'),
+)
diff --git a/openstack_dashboard/dashboards/admin/overview/views.py b/openstack_dashboard/dashboards/admin/overview/views.py
new file mode 100644
index 000000000..679250f61
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/overview/views.py
@@ -0,0 +1,48 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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
+
+from openstack_dashboard import api
+from openstack_dashboard import usage
+
+
+class GlobalOverview(usage.UsageView):
+ table_class = usage.GlobalUsageTable
+ usage_class = usage.GlobalUsage
+ template_name = 'admin/overview/usage.html'
+
+ def get_context_data(self, **kwargs):
+ context = super(GlobalOverview, self).get_context_data(**kwargs)
+ context['monitoring'] = getattr(settings, 'EXTERNAL_MONITORING', [])
+ return context
+
+ def get_data(self):
+ data = super(GlobalOverview, self).get_data()
+ # Pre-fill tenant names
+ tenants = api.keystone.tenant_list(self.request,
+ admin=True)
+ for instance in data:
+ tenant = filter(lambda t: t.id == instance.tenant_id, tenants)
+ if tenant:
+ instance.tenant_name = getattr(tenant[0], "name", None)
+ else:
+ instance.tenant_name = None
+ return data
diff --git a/openstack_dashboard/dashboards/admin/projects/__init__.py b/openstack_dashboard/dashboards/admin/projects/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/__init__.py
diff --git a/openstack_dashboard/dashboards/admin/projects/forms.py b/openstack_dashboard/dashboards/admin/projects/forms.py
new file mode 100644
index 000000000..9450ac64e
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/forms.py
@@ -0,0 +1,33 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 horizon import forms
+
+from openstack_dashboard.dashboards.admin.users.forms import CreateUserForm
+
+
+class CreateUser(CreateUserForm):
+ role_id = forms.ChoiceField(widget=forms.HiddenInput())
+ tenant_id = forms.CharField(widget=forms.HiddenInput())
+
+ def __init__(self, request, *args, **kwargs):
+ super(CreateUser, self).__init__(request, *args, **kwargs)
+ tenant_id = self.request.path.split("/")[-1]
+ self.fields['tenant_id'].initial = tenant_id
diff --git a/openstack_dashboard/dashboards/admin/projects/panel.py b/openstack_dashboard/dashboards/admin/projects/panel.py
new file mode 100644
index 000000000..8eb9757d0
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/panel.py
@@ -0,0 +1,33 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.admin import dashboard
+
+
+class Tenants(horizon.Panel):
+ name = _("Projects")
+ slug = 'projects'
+
+
+dashboard.Admin.register(Tenants)
diff --git a/openstack_dashboard/dashboards/admin/projects/tables.py b/openstack_dashboard/dashboards/admin/projects/tables.py
new file mode 100644
index 000000000..a5bdcc3a9
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/tables.py
@@ -0,0 +1,157 @@
+import logging
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+from django.utils.http import urlencode
+
+from horizon import exceptions
+from horizon import tables
+
+from openstack_dashboard import api
+from ..users.tables import UsersTable
+
+
+LOG = logging.getLogger(__name__)
+
+
+class ViewMembersLink(tables.LinkAction):
+ name = "users"
+ verbose_name = _("Modify Users")
+ url = "horizon:admin:projects:update"
+ classes = ("ajax-modal", "btn-edit")
+
+ def get_link_url(self, project):
+ step = 'update_members'
+ base_url = reverse(self.url, args=[project.id])
+ param = urlencode({"step": step})
+ return "?".join([base_url, param])
+
+
+class UsageLink(tables.LinkAction):
+ name = "usage"
+ verbose_name = _("View Usage")
+ url = "horizon:admin:projects:usage"
+ classes = ("btn-stats",)
+
+
+class CreateProject(tables.LinkAction):
+ name = "create"
+ verbose_name = _("Create Project")
+ url = "horizon:admin:projects:create"
+ classes = ("btn-launch", "ajax-modal",)
+
+
+class UpdateProject(tables.LinkAction):
+ name = "update"
+ verbose_name = _("Edit Project")
+ url = "horizon:admin:projects:update"
+ classes = ("ajax-modal", "btn-edit")
+
+
+class ModifyQuotas(tables.LinkAction):
+ name = "quotas"
+ verbose_name = "Modify Quotas"
+ url = "horizon:admin:projects:update"
+ classes = ("ajax-modal", "btn-edit")
+
+ def get_link_url(self, project):
+ step = 'update_quotas'
+ base_url = reverse(self.url, args=[project.id])
+ param = urlencode({"step": step})
+ return "?".join([base_url, param])
+
+
+class DeleteTenantsAction(tables.DeleteAction):
+ data_type_singular = _("Project")
+ data_type_plural = _("Projects")
+
+ def delete(self, request, obj_id):
+ api.keystone.tenant_delete(request, obj_id)
+
+
+class TenantFilterAction(tables.FilterAction):
+ def filter(self, table, tenants, filter_string):
+ """ Really naive case-insensitive search. """
+ # FIXME(gabriel): This should be smarter. Written for demo purposes.
+ q = filter_string.lower()
+
+ def comp(tenant):
+ if q in tenant.name.lower():
+ return True
+ return False
+
+ return filter(comp, tenants)
+
+
+class TenantsTable(tables.DataTable):
+ name = tables.Column('name', verbose_name=_('Name'))
+ description = tables.Column(lambda obj: getattr(obj, 'description', None),
+ verbose_name=_('Description'))
+ id = tables.Column('id', verbose_name=_('Project ID'))
+ enabled = tables.Column('enabled', verbose_name=_('Enabled'), status=True)
+
+ class Meta:
+ name = "tenants"
+ verbose_name = _("Projects")
+ row_actions = (ViewMembersLink, UpdateProject, UsageLink,
+ ModifyQuotas, DeleteTenantsAction)
+ table_actions = (TenantFilterAction, CreateProject,
+ DeleteTenantsAction)
+
+
+class RemoveUserAction(tables.BatchAction):
+ name = "remove_user"
+ action_present = _("Remove")
+ action_past = _("Removed")
+ data_type_singular = _("User")
+ data_type_plural = _("Users")
+ classes = ('btn-danger',)
+
+ def action(self, request, user_id):
+ tenant_id = self.table.kwargs['tenant_id']
+ api.keystone.remove_tenant_user(request, tenant_id, user_id)
+
+
+class ProjectUserRolesColumn(tables.Column):
+ def get_raw_data(self, user):
+ request = self.table.request
+ try:
+ roles = api.keystone.roles_for_user(request,
+ user.id,
+ self.table.kwargs["tenant_id"])
+ except:
+ roles = []
+ exceptions.handle(request,
+ _("Unable to retrieve role information."))
+ return ", ".join([role.name for role in roles])
+
+
+class TenantUsersTable(UsersTable):
+ roles = ProjectUserRolesColumn("roles", verbose_name=_("Roles"))
+
+ class Meta:
+ name = "tenant_users"
+ verbose_name = _("Users For Project")
+ table_actions = (RemoveUserAction,)
+ row_actions = (RemoveUserAction,)
+ columns = ("name", "email", "id", "roles", "enabled")
+
+
+class AddUserAction(tables.LinkAction):
+ name = "add_user"
+ verbose_name = _("Add To Project")
+ url = "horizon:admin:projects:add_user"
+ classes = ('ajax-modal',)
+
+ def get_link_url(self, user):
+ tenant_id = self.table.kwargs['tenant_id']
+ return reverse(self.url, args=(tenant_id, user.id))
+
+
+class AddUsersTable(UsersTable):
+ class Meta:
+ name = "add_users"
+ verbose_name = _("Add New Users")
+ table_actions = ()
+ row_actions = (AddUserAction,)
+ columns = ("name", "email", "id", "enabled")
diff --git a/openstack_dashboard/dashboards/admin/projects/templates/projects/_add_user.html b/openstack_dashboard/dashboards/admin/projects/templates/projects/_add_user.html
new file mode 100644
index 000000000..3b365cebd
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/templates/projects/_add_user.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}add_user_form{% endblock %}
+{% block form_action %}{% url horizon:admin:projects:add_user tenant_id user_id %}{% endblock %}
+
+{% block modal_id %}add_user_modal{% endblock %}
+{% block modal-header %}{% trans "Add User To Project" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "Select the user role for the project." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Add" %}" />
+ <a href="{% url horizon:admin:projects:users tenant_id %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/projects/templates/projects/_create.html b/openstack_dashboard/dashboards/admin/projects/templates/projects/_create.html
new file mode 100644
index 000000000..372878e7e
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/templates/projects/_create.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}create_tenant_form{% endblock %}
+{% block form_action %}{% url horizon:admin:projects:create %}{% endblock %}
+
+{% block modal_id %}create_tenant_modal{% endblock %}
+{% block modal-header %}{% trans "Create Project" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "From here you can create a new project to organize users." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Project" %}" />
+ <a href="{% url horizon:admin:projects:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/projects/templates/projects/_create_user.html b/openstack_dashboard/dashboards/admin/projects/templates/projects/_create_user.html
new file mode 100644
index 000000000..18fcdcad9
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/templates/projects/_create_user.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}create_user_form{% endblock %}
+{% block form_action %}{% url horizon:admin:projects:create_user tenant_id %}{% endblock %}
+
+{% block modal-header %}{% blocktrans %}Create User for project '{{ tenant_name }}'.{% endblocktrans %}{% endblock %}
+
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "From here you can create a new user to add to this project." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create User" %}" />
+ <a href="{% url horizon:admin:projects:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/projects/templates/projects/_quotas.html b/openstack_dashboard/dashboards/admin/projects/templates/projects/_quotas.html
new file mode 100644
index 000000000..9bbae7b73
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/templates/projects/_quotas.html
@@ -0,0 +1,24 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}quota_update_form{% endblock %}
+{% block form_action %}{% url horizon:admin:projects:quotas tenant.id %}{% endblock %}
+
+{% block modal-header %}{% trans "Update Quota" %}{% 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 with tenant_id=tenant.id %}From here you can edit quotas (max limits) for the project {{ tenant.name }}.{% endblocktrans %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Update Quota" %}" />
+ <a href="{% url horizon:admin:projects:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/projects/templates/projects/_update.html b/openstack_dashboard/dashboards/admin/projects/templates/projects/_update.html
new file mode 100644
index 000000000..a463e20da
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/templates/projects/_update.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}{% endblock %}
+{% block form_action %}{% url horizon:admin:projects:update tenant.id %}{% endblock %}
+
+{% block modal_id %}update_tenant_modal{% endblock %}
+{% block modal-header %}{% trans "Update Project" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "From here you can edit a project." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Update Project" %}" />
+ <a href="{% url horizon:admin:projects:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/projects/templates/projects/_update_members.html b/openstack_dashboard/dashboards/admin/projects/templates/projects/_update_members.html
new file mode 100644
index 000000000..4762c7b7f
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/templates/projects/_update_members.html
@@ -0,0 +1,39 @@
+{% load i18n %}
+
+<noscript><h3>{{ step }}</h3></noscript>
+
+<div class="project_membership">
+ <div class="header">
+ <div class="help_text">{% trans "From here you can add and remove members to this project from the list of all available users." %}</div>
+ <div class="left">
+ <div class="fake_table fake_table_header">
+ <span class="users_title">{% trans "All Users" %}</span>
+ <input type="text" name="available_users_filter" id="available_users" class="filter" value="Filter">
+ </div>
+ </div>
+ <div class="right">
+ <div class="fake_table fake_table_header">
+ <span class="users_title">{% trans "Project Members" %}</span>
+ <input type="text" name="project_members_filter" id="project_members" class="filter" value="Filter">
+ </div>
+ </div>
+ </div>
+
+ <div class="left filterable">
+ <div class="fake_table" id="available_users">
+ <ul class="available_users"></ul>
+ <ul class="no_results" id="no_available_users"><li>{% trans "No users found." %}</li></ul>
+ </div>
+ </div>
+
+ <div class="right filterable">
+ <div class="fake_table" id="project_members">
+ <ul class="project_members"></ul>
+ <ul class="no_results" id="no_project_members"><li>{% trans "No users found." %}</li></ul>
+ </div>
+ </div>
+</div>
+
+<div class="hide">
+ {% include "horizon/common/_form_fields.html" %}
+</div>
diff --git a/openstack_dashboard/dashboards/admin/projects/templates/projects/add_user.html b/openstack_dashboard/dashboards/admin/projects/templates/projects/add_user.html
new file mode 100644
index 000000000..536181203
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/templates/projects/add_user.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Add User To Project" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Add User To Project") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'admin/projects/_add_user.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/projects/templates/projects/create.html b/openstack_dashboard/dashboards/admin/projects/templates/projects/create.html
new file mode 100644
index 000000000..2b9c573b5
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/templates/projects/create.html
@@ -0,0 +1,12 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Create Project{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Create Project") %}
+{% endblock page_header %}
+
+
+{% block main %}
+ {% include 'horizon/common/_workflow.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/projects/templates/projects/create_user.html b/openstack_dashboard/dashboards/admin/projects/templates/projects/create_user.html
new file mode 100644
index 000000000..306bf669d
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/templates/projects/create_user.html
@@ -0,0 +1,12 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Add New User" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Add New User") %}
+{% endblock page_header %}
+
+
+{% block main %}
+ {% include 'horizon/common/_create_user.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/projects/templates/projects/index.html b/openstack_dashboard/dashboards/admin/projects/templates/projects/index.html
new file mode 100644
index 000000000..7bb3429ad
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/templates/projects/index.html
@@ -0,0 +1,13 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Projects{% endblock %}
+
+{% block page_header %}
+ {% url horizon:admin:projects:index as refresh_link %}
+ {# to make searchable false, just remove it from the include statement #}
+ {% include "horizon/common/_page_header.html" with title=_("Projects") refresh_link=refresh_link searchable="true" %}
+{% endblock page_header %}
+
+{% block main %}
+ {{ table.render }}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/projects/templates/projects/quotas.html b/openstack_dashboard/dashboards/admin/projects/templates/projects/quotas.html
new file mode 100644
index 000000000..99a143f7c
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/templates/projects/quotas.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Modify Project Quotas{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Update Project") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'admin/projects/_quotas.html' with form=form %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/projects/templates/projects/update.html b/openstack_dashboard/dashboards/admin/projects/templates/projects/update.html
new file mode 100644
index 000000000..2fbe3d8b7
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/templates/projects/update.html
@@ -0,0 +1,12 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Edit Project" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Edit Project") %}
+{% endblock page_header %}
+
+
+{% block main %}
+ {% include 'horizon/common/_workflow.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/projects/templates/projects/usage.csv b/openstack_dashboard/dashboards/admin/projects/templates/projects/usage.csv
new file mode 100644
index 000000000..3a9aa057d
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/templates/projects/usage.csv
@@ -0,0 +1,11 @@
+Usage Report For Period:,{{ usage.start|date:"b. d Y" }},/,{{ usage.end|date:"b. d Y" }}
+Tenant ID:,{{ usage.tenant_id }}
+Total Active VCPUs:,{{ usage.summary.instances }}
+CPU-HRs Used:,{{ usage.summary.vcpu_hours }}
+Total Active Ram (MB):,{{ usage.summary.memory_mb }}
+Total Disk Size:,{{ usage.summary.local_gb }}
+Total Disk Usage:,{{ usage.summary.disk_gb_hours }}
+
+Name,VCPUs,RamMB,DiskGB,Usage(Hours),Uptime(Seconds),State
+{% for s in usage.get_instances %}{{ s.name|addslashes }},{{ s.vcpus|addslashes }},{{ s.memory_mb|addslashes }},{{ s.local_gb|addslashes }},{{ s.hours }},{{ s.uptime }},{{ s.state|capfirst|addslashes }}
+{% endfor %}
diff --git a/openstack_dashboard/dashboards/admin/projects/templates/projects/usage.html b/openstack_dashboard/dashboards/admin/projects/templates/projects/usage.html
new file mode 100644
index 000000000..e5e77c168
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/templates/projects/usage.html
@@ -0,0 +1,14 @@
+{% extends 'base.html' %}
+{% load i18n sizeformat %}
+{% block title %}{% trans "Project Usage Overview" %}{% endblock %}
+
+{% block page_header %}
+ <div class='page-header'>
+ <h2>{% trans "Project Usage" %}</h2>
+ </div>
+{% endblock %}
+
+{% block main %}
+ {% include "horizon/common/_usage_summary.html" %}
+ {{ table.render }}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/projects/templates/projects/users.html b/openstack_dashboard/dashboards/admin/projects/templates/projects/users.html
new file mode 100644
index 000000000..b69c1b297
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/templates/projects/users.html
@@ -0,0 +1,18 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Project Users{% endblock %}
+
+{% block page_header %}
+ <div class='page-header'>
+ <h2>{% trans "Users for Project" %}: <span>{{ tenant.name }}</span></h2>
+ </div>
+{% endblock %}
+
+{% block main %}
+ <div id="tenant_users_table">
+ {{ tenant_users_table.render }}
+ </div>
+ <div id="add_users_table">
+ {{ add_users_table.render }}
+ </div>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/projects/tests.py b/openstack_dashboard/dashboards/admin/projects/tests.py
new file mode 100644
index 000000000..2ea5d0283
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/tests.py
@@ -0,0 +1,842 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 import http
+from django.core.urlresolvers import reverse
+
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+from .workflows import CreateProject, UpdateProject
+from .views import QUOTA_FIELDS
+
+INDEX_URL = reverse('horizon:admin:projects:index')
+
+
+class TenantsViewTests(test.BaseAdminViewTests):
+ def test_index(self):
+ self.mox.StubOutWithMock(api.keystone, 'tenant_list')
+ api.keystone.tenant_list(IsA(http.HttpRequest), admin=True) \
+ .AndReturn(self.tenants.list())
+ self.mox.ReplayAll()
+
+ res = self.client.get(INDEX_URL)
+ self.assertTemplateUsed(res, 'admin/projects/index.html')
+ self.assertItemsEqual(res.context['table'].data, self.tenants.list())
+
+
+class CreateProjectWorkflowTests(test.BaseAdminViewTests):
+ def _get_project_info(self, project):
+ project_info = {"tenant_name": project.name,
+ "description": project.description,
+ "enabled": project.enabled}
+ return project_info
+
+ def _get_workflow_fields(self, project):
+ project_info = {"name": project.name,
+ "description": project.description,
+ "enabled": project.enabled}
+ return project_info
+
+ def _get_quota_info(self, quota):
+ quota_data = {}
+ for field in QUOTA_FIELDS:
+ quota_data[field] = int(getattr(quota, field, None))
+ return quota_data
+
+ def _get_workflow_data(self, project, quota):
+ project_info = self._get_workflow_fields(project)
+ quota_data = self._get_quota_info(quota)
+ project_info.update(quota_data)
+ return project_info
+
+ @test.create_stubs({api: ('tenant_quota_defaults',
+ 'get_default_role',),
+ api.keystone: ('user_list',
+ 'role_list',)})
+ def test_add_project_get(self):
+ quota = self.quotas.first()
+ default_role = self.roles.first()
+ users = self.users.list()
+ roles = self.roles.list()
+
+ api.tenant_quota_defaults(IsA(http.HttpRequest), self.tenant.id) \
+ .AndReturn(quota)
+
+ # init
+ api.get_default_role(IsA(http.HttpRequest)).AndReturn(default_role)
+ api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:projects:create')
+ res = self.client.get(url)
+
+ self.assertTemplateUsed(res, 'admin/projects/create.html')
+
+ workflow = res.context['workflow']
+ self.assertEqual(res.context['workflow'].name, CreateProject.name)
+
+ step = workflow.get_step("createprojectinfoaction")
+ self.assertEqual(step.action.initial['ram'], quota.ram)
+ self.assertEqual(step.action.initial['injected_files'],
+ quota.injected_files)
+ self.assertQuerysetEqual(workflow.steps,
+ ['<CreateProjectInfo: createprojectinfoaction>',
+ '<UpdateProjectMembers: update_members>',
+ '<UpdateProjectQuota: update_quotas>'])
+
+ @test.create_stubs({api: ('get_default_role',
+ 'tenant_quota_defaults',
+ 'add_tenant_user_role',),
+ api.keystone: ('tenant_create',
+ 'user_list',
+ 'role_list'),
+ api.nova: ('tenant_quota_update',)})
+ def test_add_project_post(self):
+ project = self.tenants.first()
+ quota = self.quotas.first()
+ default_role = self.roles.first()
+ users = self.users.list()
+ roles = self.roles.list()
+
+ # init
+ api.tenant_quota_defaults(IsA(http.HttpRequest), self.tenant.id) \
+ .AndReturn(quota)
+
+ api.get_default_role(IsA(http.HttpRequest)).AndReturn(default_role)
+ api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ # contribute
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ # handle
+ project_details = self._get_project_info(project)
+ quota_data = self._get_quota_info(quota)
+
+ api.keystone.tenant_create(IsA(http.HttpRequest), **project_details) \
+ .AndReturn(project)
+
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ workflow_data = {}
+ for role in roles:
+ if "role_" + role.id in workflow_data:
+ ulist = workflow_data["role_" + role.id]
+ for user in ulist:
+ api.add_tenant_user_role(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ user_id=user,
+ role_id=role.id)
+
+ api.nova.tenant_quota_update(IsA(http.HttpRequest),
+ project.id,
+ **quota_data)
+
+ self.mox.ReplayAll()
+
+ workflow_data.update(self._get_workflow_data(project, quota))
+
+ url = reverse('horizon:admin:projects:create')
+ res = self.client.post(url, workflow_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('tenant_quota_defaults',
+ 'get_default_role',),
+ api.keystone: ('user_list',
+ 'role_list',)})
+ def test_add_project_quota_defaults_error(self):
+ default_role = self.roles.first()
+ users = self.users.list()
+ roles = self.roles.list()
+
+ # init
+ api.tenant_quota_defaults(IsA(http.HttpRequest), self.tenant.id) \
+ .AndRaise(self.exceptions.nova)
+
+ api.get_default_role(IsA(http.HttpRequest)).AndReturn(default_role)
+ api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:projects:create')
+ res = self.client.get(url)
+
+ self.assertTemplateUsed(res, 'admin/projects/create.html')
+ self.assertContains(res, "Unable to retrieve default quota values")
+
+ @test.create_stubs({api: ('get_default_role',
+ 'tenant_quota_defaults',),
+ api.keystone: ('tenant_create',
+ 'user_list',
+ 'role_list',)})
+ def test_add_project_tenant_create_error(self):
+ project = self.tenants.first()
+ quota = self.quotas.first()
+ default_role = self.roles.first()
+ users = self.users.list()
+ roles = self.roles.list()
+
+ # init
+ api.tenant_quota_defaults(IsA(http.HttpRequest), self.tenant.id) \
+ .AndReturn(quota)
+
+ api.get_default_role(IsA(http.HttpRequest)).AndReturn(default_role)
+ api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ # contribute
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ # handle
+ project_details = self._get_project_info(project)
+
+ api.keystone.tenant_create(IsA(http.HttpRequest), **project_details) \
+ .AndRaise(self.exceptions.keystone)
+
+ self.mox.ReplayAll()
+
+ workflow_data = self._get_workflow_data(project, quota)
+
+ url = reverse('horizon:admin:projects:create')
+ res = self.client.post(url, workflow_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('get_default_role',
+ 'tenant_quota_defaults',
+ 'add_tenant_user_role',),
+ api.keystone: ('tenant_create',
+ 'user_list',
+ 'role_list'),
+ api.nova: ('tenant_quota_update',)})
+ def test_add_project_quota_update_error(self):
+ project = self.tenants.first()
+ quota = self.quotas.first()
+ default_role = self.roles.first()
+ users = self.users.list()
+ roles = self.roles.list()
+
+ # init
+ api.tenant_quota_defaults(IsA(http.HttpRequest), self.tenant.id) \
+ .AndReturn(quota)
+
+ api.get_default_role(IsA(http.HttpRequest)).AndReturn(default_role)
+ api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ # contribute
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ # handle
+ project_details = self._get_project_info(project)
+ quota_data = self._get_quota_info(quota)
+
+ api.keystone.tenant_create(IsA(http.HttpRequest), **project_details) \
+ .AndReturn(project)
+
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ workflow_data = {}
+ for role in roles:
+ if "role_" + role.id in workflow_data:
+ ulist = workflow_data["role_" + role.id]
+ for user in ulist:
+ api.add_tenant_user_role(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ user_id=user,
+ role_id=role.id)
+
+ api.nova.tenant_quota_update(IsA(http.HttpRequest),
+ project.id,
+ **quota_data) \
+ .AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ workflow_data.update(self._get_workflow_data(project, quota))
+
+ url = reverse('horizon:admin:projects:create')
+ res = self.client.post(url, workflow_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('get_default_role',
+ 'tenant_quota_defaults',
+ 'add_tenant_user_role',),
+ api.keystone: ('tenant_create',
+ 'user_list',
+ 'role_list',),
+ api.nova: ('tenant_quota_update',)})
+ def test_add_project_user_update_error(self):
+ project = self.tenants.first()
+ quota = self.quotas.first()
+ default_role = self.roles.first()
+ users = self.users.list()
+ roles = self.roles.list()
+
+ # init
+ api.tenant_quota_defaults(IsA(http.HttpRequest), self.tenant.id) \
+ .AndReturn(quota)
+
+ api.get_default_role(IsA(http.HttpRequest)).AndReturn(default_role)
+ api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ # contribute
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ # handle
+ project_details = self._get_project_info(project)
+ quota_data = self._get_quota_info(quota)
+
+ api.keystone.tenant_create(IsA(http.HttpRequest), **project_details) \
+ .AndReturn(project)
+
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ workflow_data = {}
+ for role in roles:
+ if "role_" + role.id in workflow_data:
+ ulist = workflow_data["role_" + role.id]
+ for user in ulist:
+ api.add_tenant_user_role(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ user_id=user,
+ role_id=role.id) \
+ .AndRaise(self.exceptions.keystone)
+ break
+ break
+
+ api.nova.tenant_quota_update(IsA(http.HttpRequest),
+ project.id,
+ **quota_data)
+
+ self.mox.ReplayAll()
+
+ workflow_data.update(self._get_workflow_data(project, quota))
+
+ url = reverse('horizon:admin:projects:create')
+ res = self.client.post(url, workflow_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('get_default_role',
+ 'tenant_quota_defaults',),
+ api.keystone: ('user_list',
+ 'role_list',)})
+ def test_add_project_missing_field_error(self):
+ project = self.tenants.first()
+ quota = self.quotas.first()
+ default_role = self.roles.first()
+ users = self.users.list()
+ roles = self.roles.list()
+
+ # init
+ api.tenant_quota_defaults(IsA(http.HttpRequest), self.tenant.id) \
+ .AndReturn(quota)
+
+ api.get_default_role(IsA(http.HttpRequest)).AndReturn(default_role)
+ api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ # contribute
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ self.mox.ReplayAll()
+
+ workflow_data = self._get_workflow_data(project, quota)
+ workflow_data["name"] = ""
+
+ url = reverse('horizon:admin:projects:create')
+ res = self.client.post(url, workflow_data)
+
+ self.assertContains(res, "field is required")
+
+
+class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
+ def _get_quota_info(self, quota):
+ quota_data = {}
+ for field in QUOTA_FIELDS:
+ quota_data[field] = int(getattr(quota, field, None))
+ return quota_data
+
+ @test.create_stubs({api: ('get_default_role',
+ 'roles_for_user',
+ 'tenant_get',
+ 'tenant_quota_get',),
+ api.keystone: ('user_list',
+ 'role_list',)})
+ def test_update_project_get(self):
+ project = self.tenants.first()
+ quota = self.quotas.first()
+ default_role = self.roles.first()
+ users = self.users.list()
+ roles = self.roles.list()
+
+ api.tenant_get(IsA(http.HttpRequest), self.tenant.id, admin=True) \
+ .AndReturn(project)
+ api.tenant_quota_get(IsA(http.HttpRequest), self.tenant.id) \
+ .AndReturn(quota)
+
+ api.get_default_role(IsA(http.HttpRequest)).AndReturn(default_role)
+ api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ for user in users:
+ api.roles_for_user(IsA(http.HttpRequest),
+ user.id,
+ self.tenant.id).AndReturn(roles)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:projects:update',
+ args=[self.tenant.id])
+ res = self.client.get(url)
+
+ self.assertTemplateUsed(res, 'admin/projects/update.html')
+
+ workflow = res.context['workflow']
+ self.assertEqual(res.context['workflow'].name, UpdateProject.name)
+
+ step = workflow.get_step("update_info")
+ self.assertEqual(step.action.initial['ram'], quota.ram)
+ self.assertEqual(step.action.initial['injected_files'],
+ quota.injected_files)
+ self.assertEqual(step.action.initial['name'], project.name)
+ self.assertEqual(step.action.initial['description'],
+ project.description)
+ self.assertQuerysetEqual(workflow.steps,
+ ['<UpdateProjectInfo: update_info>',
+ '<UpdateProjectMembers: update_members>',
+ '<UpdateProjectQuota: update_quotas>'])
+
+ @test.create_stubs({api: ('tenant_get',
+ 'tenant_quota_get',
+ 'tenant_update',
+ 'tenant_quota_update',
+ 'get_default_role',
+ 'roles_for_user',
+ 'remove_tenant_user_role',
+ 'add_tenant_user_role'),
+ api.keystone: ('user_list',
+ 'role_list',)})
+ def test_update_project_post(self):
+ project = self.tenants.first()
+ quota = self.quotas.first()
+ default_role = self.roles.first()
+ users = self.users.list()
+ roles = self.roles.list()
+ current_roles = self.roles.list()
+
+ # get/init
+ api.tenant_get(IsA(http.HttpRequest), self.tenant.id, admin=True) \
+ .AndReturn(project)
+ api.tenant_quota_get(IsA(http.HttpRequest), self.tenant.id) \
+ .AndReturn(quota)
+
+ api.get_default_role(IsA(http.HttpRequest)).AndReturn(default_role)
+ api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ workflow_data = {}
+ for user in users:
+ api.roles_for_user(IsA(http.HttpRequest),
+ user.id,
+ self.tenant.id).AndReturn(roles)
+ role_ids = [role.id for role in roles]
+ if role_ids:
+ workflow_data.setdefault("role_" + role_ids[0], []) \
+ .append(user.id)
+
+ # update some fields
+ project._info["name"] = "updated name"
+ project._info["description"] = "updated description"
+ quota.metadata_items = 444
+ quota.volumes = 444
+
+ updated_project = {"tenant_name": project._info["name"],
+ "tenant_id": project.id,
+ "description": project._info["description"],
+ "enabled": project.enabled}
+ updated_quota = self._get_quota_info(quota)
+
+ # contribute
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ # handle
+ api.tenant_update(IsA(http.HttpRequest), **updated_project) \
+ .AndReturn(project)
+
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+ api.keystone.user_list(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id).AndReturn(users)
+
+ for user in users:
+ api.roles_for_user(IsA(http.HttpRequest),
+ user.id,
+ self.tenant.id) \
+ .AndReturn(current_roles)
+ for role in roles:
+ if "role_" + role.id in workflow_data:
+ ulist = workflow_data["role_" + role.id]
+ if role not in current_roles:
+ api.add_tenant_user_role(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ user_id=user,
+ role_id=role.id)
+ else:
+ current_roles.pop(current_roles.index(role))
+ for to_delete in current_roles:
+ api.remove_tenant_user_role(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ user_id=user.id,
+ role_id=to_delete.id)
+ for role in roles:
+ if "role_" + role.id in workflow_data:
+ ulist = workflow_data["role_" + role.id]
+ for user in ulist:
+ if not filter(lambda x: user == x.id, users):
+ api.add_tenant_user_role(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ user_id=user,
+ role_id=role.id)
+
+ api.tenant_quota_update(IsA(http.HttpRequest),
+ project.id,
+ **updated_quota)
+
+ self.mox.ReplayAll()
+
+ # submit form data
+ project_data = {"name": project._info["name"],
+ "id": project.id,
+ "description": project._info["description"],
+ "enabled": project.enabled}
+ workflow_data.update(project_data)
+ workflow_data.update(updated_quota)
+ url = reverse('horizon:admin:projects:update',
+ args=[self.tenant.id])
+ res = self.client.post(url, workflow_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('tenant_get',)})
+ def test_update_project_get_error(self):
+
+ api.tenant_get(IsA(http.HttpRequest), self.tenant.id, admin=True) \
+ .AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:admin:projects:update',
+ args=[self.tenant.id])
+ res = self.client.get(url)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('tenant_get',
+ 'tenant_quota_get',
+ 'tenant_update',
+ 'tenant_quota_update',
+ 'get_default_role',
+ 'roles_for_user',
+ 'remove_tenant_user',
+ 'add_tenant_user_role'),
+ api.keystone: ('user_list',
+ 'role_list',)})
+ def test_update_project_tenant_update_error(self):
+ project = self.tenants.first()
+ quota = self.quotas.first()
+ default_role = self.roles.first()
+ users = self.users.list()
+ roles = self.roles.list()
+
+ # get/init
+ api.tenant_get(IsA(http.HttpRequest), self.tenant.id, admin=True) \
+ .AndReturn(project)
+ api.tenant_quota_get(IsA(http.HttpRequest), self.tenant.id) \
+ .AndReturn(quota)
+
+ api.get_default_role(IsA(http.HttpRequest)).AndReturn(default_role)
+ api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ workflow_data = {}
+ for user in users:
+ api.roles_for_user(IsA(http.HttpRequest),
+ user.id,
+ self.tenant.id).AndReturn(roles)
+ role_ids = [role.id for role in roles]
+ if role_ids:
+ workflow_data.setdefault("role_" + role_ids[0], []) \
+ .append(user.id)
+
+ # update some fields
+ project._info["name"] = "updated name"
+ project._info["description"] = "updated description"
+ quota.metadata_items = 444
+ quota.volumes = 444
+
+ updated_project = {"tenant_name": project._info["name"],
+ "tenant_id": project.id,
+ "description": project._info["description"],
+ "enabled": project.enabled}
+ updated_quota = self._get_quota_info(quota)
+
+ # contribute
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ # handle
+ api.tenant_update(IsA(http.HttpRequest), **updated_project) \
+ .AndRaise(self.exceptions.keystone)
+
+ self.mox.ReplayAll()
+
+ # submit form data
+ project_data = {"name": project._info["name"],
+ "id": project.id,
+ "description": project._info["description"],
+ "enabled": project.enabled}
+ workflow_data.update(project_data)
+ workflow_data.update(updated_quota)
+ url = reverse('horizon:admin:projects:update',
+ args=[self.tenant.id])
+ res = self.client.post(url, workflow_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('tenant_get',
+ 'tenant_quota_get',
+ 'tenant_update',
+ 'tenant_quota_update',
+ 'get_default_role',
+ 'roles_for_user',
+ 'remove_tenant_user_role',
+ 'add_tenant_user_role'),
+ api.keystone: ('user_list',
+ 'role_list',)})
+ def test_update_project_quota_update_error(self):
+ project = self.tenants.first()
+ quota = self.quotas.first()
+ default_role = self.roles.first()
+ users = self.users.list()
+ roles = self.roles.list()
+ current_roles = self.roles.list()
+
+ # get/init
+ api.tenant_get(IsA(http.HttpRequest), self.tenant.id, admin=True) \
+ .AndReturn(project)
+ api.tenant_quota_get(IsA(http.HttpRequest), self.tenant.id) \
+ .AndReturn(quota)
+
+ api.get_default_role(IsA(http.HttpRequest)).AndReturn(default_role)
+ api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ workflow_data = {}
+ for user in users:
+ api.roles_for_user(IsA(http.HttpRequest),
+ user.id,
+ self.tenant.id).AndReturn(roles)
+ role_ids = [role.id for role in roles]
+ if role_ids:
+ workflow_data.setdefault("role_" + role_ids[0], []) \
+ .append(user.id)
+
+ # update some fields
+ project._info["name"] = "updated name"
+ project._info["description"] = "updated description"
+ quota.metadata_items = 444
+ quota.volumes = 444
+
+ updated_project = {"tenant_name": project._info["name"],
+ "tenant_id": project.id,
+ "description": project._info["description"],
+ "enabled": project.enabled}
+ updated_quota = self._get_quota_info(quota)
+
+ # contribute
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ # handle
+ # handle
+ api.tenant_update(IsA(http.HttpRequest), **updated_project) \
+ .AndReturn(project)
+
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+ api.keystone.user_list(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id).AndReturn(users)
+
+ for user in users:
+ api.roles_for_user(IsA(http.HttpRequest),
+ user.id,
+ self.tenant.id) \
+ .AndReturn(current_roles)
+ for role in roles:
+ if "role_" + role.id in workflow_data:
+ ulist = workflow_data["role_" + role.id]
+ if role not in current_roles:
+ api.add_tenant_user_role(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ user_id=user,
+ role_id=role.id)
+ else:
+ current_roles.pop(current_roles.index(role))
+ for to_delete in current_roles:
+ api.remove_tenant_user_role(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ user_id=user.id,
+ role_id=to_delete.id)
+ for role in roles:
+ if "role_" + role.id in workflow_data:
+ ulist = workflow_data["role_" + role.id]
+ for user in ulist:
+ if not filter(lambda x: user == x.id, users):
+ api.add_tenant_user_role(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ user_id=user,
+ role_id=role.id)
+
+ api.tenant_quota_update(IsA(http.HttpRequest),
+ project.id,
+ **updated_quota).AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ # submit form data
+ project_data = {"name": project._info["name"],
+ "id": project.id,
+ "description": project._info["description"],
+ "enabled": project.enabled}
+ workflow_data.update(project_data)
+ workflow_data.update(updated_quota)
+ url = reverse('horizon:admin:projects:update',
+ args=[self.tenant.id])
+ res = self.client.post(url, workflow_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('tenant_get',
+ 'tenant_quota_get',
+ 'tenant_update',
+ 'get_default_role',
+ 'roles_for_user',
+ 'remove_tenant_user_role',
+ 'add_tenant_user_role'),
+ api.keystone: ('user_list',
+ 'role_list',)})
+ def test_update_project_member_update_error(self):
+ project = self.tenants.first()
+ quota = self.quotas.first()
+ default_role = self.roles.first()
+ users = self.users.list()
+ roles = self.roles.list()
+ current_roles = self.roles.list()
+
+ # get/init
+ api.tenant_get(IsA(http.HttpRequest), self.tenant.id, admin=True) \
+ .AndReturn(project)
+ api.tenant_quota_get(IsA(http.HttpRequest), self.tenant.id) \
+ .AndReturn(quota)
+
+ api.get_default_role(IsA(http.HttpRequest)).AndReturn(default_role)
+ api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ workflow_data = {}
+ for user in users:
+ api.roles_for_user(IsA(http.HttpRequest),
+ user.id,
+ self.tenant.id).AndReturn(roles)
+ role_ids = [role.id for role in roles]
+ if role_ids:
+ workflow_data.setdefault("role_" + role_ids[0], []) \
+ .append(user.id)
+
+ # update some fields
+ project._info["name"] = "updated name"
+ project._info["description"] = "updated description"
+ quota.metadata_items = 444
+ quota.volumes = 444
+
+ updated_project = {"tenant_name": project._info["name"],
+ "tenant_id": project.id,
+ "description": project._info["description"],
+ "enabled": project.enabled}
+ updated_quota = self._get_quota_info(quota)
+
+ # contribute
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+
+ # handle
+ api.tenant_update(IsA(http.HttpRequest), **updated_project) \
+ .AndReturn(project)
+
+ api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
+ api.keystone.user_list(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id).AndReturn(users)
+
+ for user in users:
+ api.roles_for_user(IsA(http.HttpRequest),
+ user.id,
+ self.tenant.id) \
+ .AndReturn(current_roles)
+ for role in roles:
+ if "role_" + role.id in workflow_data:
+ if role not in current_roles:
+ api.add_tenant_user_role(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ user_id=user,
+ role_id=role.id)
+ else:
+ current_roles.pop(current_roles.index(role))
+ for to_delete in current_roles:
+ api.remove_tenant_user_role(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ user_id=user.id,
+ role_id=to_delete.id) \
+ .AndRaise(self.exceptions.nova)
+ break
+ break
+
+ self.mox.ReplayAll()
+
+ # submit form data
+ project_data = {"name": project._info["name"],
+ "id": project.id,
+ "description": project._info["description"],
+ "enabled": project.enabled}
+ workflow_data.update(project_data)
+ workflow_data.update(updated_quota)
+ url = reverse('horizon:admin:projects:update',
+ args=[self.tenant.id])
+ res = self.client.post(url, workflow_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
diff --git a/openstack_dashboard/dashboards/admin/projects/urls.py b/openstack_dashboard/dashboards/admin/projects/urls.py
new file mode 100644
index 000000000..59369302c
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/urls.py
@@ -0,0 +1,37 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import patterns, url
+
+from .views import (IndexView, TenantUsageView,
+ CreateProjectView, UpdateProjectView,
+ CreateUserView)
+
+
+urlpatterns = patterns('',
+ url(r'^$', IndexView.as_view(), name='index'),
+ url(r'^create$', CreateProjectView.as_view(), name='create'),
+ url(r'^(?P<tenant_id>[^/]+)/update/$',
+ UpdateProjectView.as_view(), name='update'),
+ url(r'^(?P<tenant_id>[^/]+)/usage/$',
+ TenantUsageView.as_view(), name='usage'),
+ url(r'^(?P<tenant_id>[^/]+)/create_user/$',
+ CreateUserView.as_view(), name='create_user'),
+)
diff --git a/openstack_dashboard/dashboards/admin/projects/views.py b/openstack_dashboard/dashboards/admin/projects/views.py
new file mode 100644
index 000000000..409ac3ca2
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/views.py
@@ -0,0 +1,203 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse, reverse_lazy
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tables
+from horizon import workflows
+
+from openstack_dashboard import api
+from openstack_dashboard import usage
+from openstack_dashboard.dashboards.admin.users.views import CreateView
+from .forms import CreateUser
+from .tables import TenantsTable, TenantUsersTable, AddUsersTable
+from .workflows import CreateProject, UpdateProject
+
+LOG = logging.getLogger(__name__)
+
+
+QUOTA_FIELDS = ("metadata_items",
+ "cores",
+ "instances",
+ "injected_files",
+ "injected_file_content_bytes",
+ "volumes",
+ "gigabytes",
+ "ram",
+ "floating_ips")
+
+PROJECT_INFO_FIELDS = ("name",
+ "description",
+ "enabled")
+
+INDEX_URL = "horizon:admin:projects:index"
+
+
+class TenantContextMixin(object):
+ def get_object(self):
+ if not hasattr(self, "_object"):
+ tenant_id = self.kwargs['tenant_id']
+ try:
+ self._object = api.keystone.tenant_get(self.request,
+ tenant_id,
+ admin=True)
+ except:
+ exceptions.handle(self.request,
+ _('Unable to retrieve project information.'),
+ redirect=reverse(INDEX_URL))
+ return self._object
+
+ def get_context_data(self, **kwargs):
+ context = super(TenantContextMixin, self).get_context_data(**kwargs)
+ context['tenant'] = self.get_object()
+ return context
+
+
+class IndexView(tables.DataTableView):
+ table_class = TenantsTable
+ template_name = 'admin/projects/index.html'
+
+ def get_data(self):
+ tenants = []
+ try:
+ tenants = api.keystone.tenant_list(self.request, admin=True)
+ except:
+ exceptions.handle(self.request,
+ _("Unable to retrieve project list."))
+ tenants.sort(key=lambda x: x.id, reverse=True)
+ return tenants
+
+
+class UsersView(tables.MultiTableView):
+ table_classes = (TenantUsersTable, AddUsersTable)
+ template_name = 'admin/projects/users.html'
+
+ def _get_shared_data(self, *args, **kwargs):
+ tenant_id = self.kwargs["tenant_id"]
+ if not hasattr(self, "_shared_data"):
+ try:
+ tenant = api.keystone.tenant_get(self.request,
+ tenant_id,
+ admin=True)
+ all_users = api.keystone.user_list(self.request)
+ tenant_users = api.keystone.user_list(self.request, tenant_id)
+ self._shared_data = {'tenant': tenant,
+ 'all_users': all_users,
+ 'tenant_users': tenant_users}
+ except:
+ exceptions.handle(self.request,
+ _("Unable to retrieve users."),
+ redirect=reverse(INDEX_URL))
+ return self._shared_data
+
+ def get_tenant_users_data(self):
+ return self._get_shared_data()["tenant_users"]
+
+ def get_add_users_data(self):
+ tenant_users = self._get_shared_data()["tenant_users"]
+ all_users = self._get_shared_data()["all_users"]
+ tenant_user_ids = [user.id for user in tenant_users]
+ return filter(lambda u: u.id not in tenant_user_ids, all_users)
+
+ def get_context_data(self, **kwargs):
+ context = super(UsersView, self).get_context_data(**kwargs)
+ context['tenant'] = self._get_shared_data()["tenant"]
+ return context
+
+
+class TenantUsageView(usage.UsageView):
+ table_class = usage.TenantUsageTable
+ usage_class = usage.TenantUsage
+ template_name = 'admin/projects/usage.html'
+
+ def get_data(self):
+ super(TenantUsageView, self).get_data()
+ return self.usage.get_instances()
+
+
+class CreateProjectView(workflows.WorkflowView):
+ workflow_class = CreateProject
+ template_name = "admin/projects/create.html"
+
+ def get_initial(self):
+ initial = super(CreateProjectView, self).get_initial()
+
+ # get initial quota defaults
+ try:
+ quota_defaults = api.tenant_quota_defaults(self.request,
+ self.request.user.tenant_id)
+ for field in QUOTA_FIELDS:
+ initial[field] = getattr(quota_defaults, field, None)
+
+ except:
+ error_msg = _('Unable to retrieve default quota values.')
+ self.add_error_to_step(error_msg, 'update_quotas')
+
+ return initial
+
+
+class UpdateProjectView(workflows.WorkflowView):
+ workflow_class = UpdateProject
+ template_name = "admin/projects/update.html"
+
+ def get_initial(self):
+ initial = super(UpdateProjectView, self).get_initial()
+
+ project_id = self.kwargs['tenant_id']
+ initial['project_id'] = project_id
+
+ try:
+ # get initial project info
+ project_info = api.tenant_get(self.request, project_id, admin=True)
+ for field in PROJECT_INFO_FIELDS:
+ initial[field] = getattr(project_info, field, None)
+
+ # get initial project quota
+ quota_data = api.tenant_quota_get(self.request, project_id)
+ for field in QUOTA_FIELDS:
+ initial[field] = getattr(quota_data, field, None)
+ except:
+ exceptions.handle(self.request,
+ _('Unable to retrieve project details.'),
+ redirect=reverse(INDEX_URL))
+ return initial
+
+
+class CreateUserView(CreateView):
+ form_class = CreateUser
+ template_name = "admin/projects/create_user.html"
+ success_url = reverse_lazy('horizon:admin:projects:index')
+
+ def get_initial(self):
+ default_role = api.keystone.get_default_role(self.request)
+ return {'role_id': getattr(default_role, "id", None),
+ 'tenant_id': self.kwargs['tenant_id']}
+
+ def get_context_data(self, **kwargs):
+ context = super(CreateUserView, self).get_context_data(**kwargs)
+ context['tenant_id'] = self.kwargs['tenant_id']
+ context['tenant_name'] = api.tenant_get(self.request,
+ self.kwargs['tenant_id'],
+ admin=True).name
+ return context
diff --git a/openstack_dashboard/dashboards/admin/projects/workflows.py b/openstack_dashboard/dashboards/admin/projects/workflows.py
new file mode 100644
index 000000000..e6c72f7a2
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/projects/workflows.py
@@ -0,0 +1,366 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 as _
+from django.core.urlresolvers import reverse
+
+from horizon import exceptions
+from horizon import workflows
+from horizon import forms
+
+from openstack_dashboard import api
+
+
+INDEX_URL = "horizon:admin:projects:index"
+ADD_USER_URL = "horizon:admin:projects:create_user"
+
+
+class UpdateProjectQuotaAction(workflows.Action):
+ ifcb_label = _("Injected File Content Bytes")
+ metadata_items = forms.IntegerField(min_value=0, label=_("Metadata Items"))
+ cores = forms.IntegerField(min_value=0, label=_("VCPUs"))
+ instances = forms.IntegerField(min_value=0, label=_("Instances"))
+ injected_files = forms.IntegerField(min_value=0, label=_("Injected Files"))
+ injected_file_content_bytes = forms.IntegerField(min_value=0,
+ label=ifcb_label)
+ volumes = forms.IntegerField(min_value=0, label=_("Volumes"))
+ gigabytes = forms.IntegerField(min_value=0, label=_("Gigabytes"))
+ ram = forms.IntegerField(min_value=0, label=_("RAM (MB)"))
+ floating_ips = forms.IntegerField(min_value=0, label=_("Floating IPs"))
+
+ class Meta:
+ name = _("Quota")
+ slug = 'update_quotas'
+ help_text = _("From here you can set quotas "
+ "(max limits) for the project.")
+
+
+class UpdateProjectQuota(workflows.Step):
+ action_class = UpdateProjectQuotaAction
+ depends_on = ("project_id",)
+ contributes = ("metadata_items",
+ "cores",
+ "instances",
+ "injected_files",
+ "injected_file_content_bytes",
+ "volumes",
+ "gigabytes",
+ "ram",
+ "floating_ips")
+
+
+class CreateProjectInfoAction(workflows.Action):
+ name = forms.CharField(label=_("Name"))
+ description = forms.CharField(
+ widget=forms.widgets.Textarea(),
+ label=_("Description"),
+ required=False)
+ enabled = forms.BooleanField(label=_("Enabled"),
+ required=False,
+ initial=True)
+
+ class Meta:
+ name = _("Project Info")
+ help_text = _("From here you can create a new "
+ "project to organize users.")
+
+
+class CreateProjectInfo(workflows.Step):
+ action_class = CreateProjectInfoAction
+ contributes = ("project_id",
+ "name",
+ "description",
+ "enabled")
+
+
+class UpdateProjectMembersAction(workflows.Action):
+ default_role = forms.CharField(required=False)
+
+ def __init__(self, request, *args, **kwargs):
+ super(UpdateProjectMembersAction, self).__init__(request,
+ *args,
+ **kwargs)
+ err_msg = _('Unable to retrieve user list. Please try again later.')
+ project_id = ''
+ if 'project_id' in args[0]:
+ project_id = args[0]['project_id']
+
+ # Get the default role
+ try:
+ default_role = api.get_default_role(self.request).id
+ except:
+ exceptions.handle(self.request,
+ err_msg,
+ redirect=reverse(INDEX_URL))
+ self.fields['default_role'].initial = default_role
+
+ # Get list of available users
+ all_users = []
+ try:
+ all_users = api.keystone.user_list(request)
+ except:
+ exceptions.handle(request, err_msg)
+ users_list = [(user.id, user.name) for user in all_users]
+
+ # Get list of roles
+ role_list = []
+ try:
+ role_list = api.keystone.role_list(request)
+ except:
+ exceptions.handle(request,
+ err_msg,
+ redirect=reverse(INDEX_URL))
+ for role in role_list:
+ field_name = "role_" + role.id
+ label = _(role.name)
+ self.fields[field_name] = forms.MultipleChoiceField(required=False,
+ label=label)
+ self.fields[field_name].choices = users_list
+ self.fields[field_name].initial = []
+
+ # Figure out users & roles
+ if project_id:
+ for user in all_users:
+ try:
+ roles = api.roles_for_user(self.request,
+ user.id,
+ project_id)
+ except:
+ exceptions.handle(request,
+ err_msg,
+ redirect=reverse(INDEX_URL))
+ if roles:
+ primary_role = roles[0].id
+ self.fields["role_" + primary_role].initial.append(user.id)
+
+ class Meta:
+ name = _("Project Members")
+ slug = "update_members"
+
+
+class UpdateProjectMembers(workflows.Step):
+ action_class = UpdateProjectMembersAction
+ template_name = "admin/projects/_update_members.html"
+
+ def contribute(self, data, context):
+ if data:
+ try:
+ roles = api.keystone.role_list(self.workflow.request)
+ except:
+ exceptions.handle(self.workflow.request,
+ _('Unable to retrieve user list.'))
+
+ post = self.workflow.request.POST
+ for role in roles:
+ field = "role_" + role.id
+ context[field] = post.getlist(field)
+ return context
+
+
+class CreateProject(workflows.Workflow):
+ slug = "add_project"
+ name = _("Add Project")
+ finalize_button_name = _("Finish")
+ success_message = _('Created new project "%s".')
+ failure_message = _('Unable to create project "%s".')
+ success_url = "horizon:admin:projects:index"
+ default_steps = (CreateProjectInfo,
+ UpdateProjectMembers,
+ UpdateProjectQuota)
+
+ def format_status_message(self, message):
+ return message % self.context.get('name', 'unknown project')
+
+ def handle(self, request, data):
+ # create the project
+ try:
+ desc = data['description']
+ self.object = api.keystone.tenant_create(request,
+ tenant_name=data['name'],
+ description=desc,
+ enabled=data['enabled'])
+ except:
+ exceptions.handle(request, ignore=True)
+ return False
+
+ project_id = self.object.id
+
+ # update project members
+ users_to_add = 0
+ try:
+ available_roles = api.keystone.role_list(request)
+
+ # count how many users are to be added
+ for role in available_roles:
+ role_list = data["role_" + role.id]
+ users_to_add += len(role_list)
+ # add new users to project
+ for role in available_roles:
+ role_list = data["role_" + role.id]
+ users_added = 0
+ for user in role_list:
+ api.add_tenant_user_role(request,
+ tenant_id=project_id,
+ user_id=user,
+ role_id=role.id)
+ users_added += 1
+ users_to_add -= users_added
+ except:
+ exceptions.handle(request, _('Failed to add %s project members '
+ 'and set project quotas.'
+ % users_to_add))
+
+ # update the project quota
+ ifcb = data['injected_file_content_bytes']
+ try:
+ api.nova.tenant_quota_update(request,
+ project_id,
+ metadata_items=data['metadata_items'],
+ injected_file_content_bytes=ifcb,
+ volumes=data['volumes'],
+ gigabytes=data['gigabytes'],
+ ram=data['ram'],
+ floating_ips=data['floating_ips'],
+ instances=data['instances'],
+ injected_files=data['injected_files'],
+ cores=data['cores'])
+ except:
+ exceptions.handle(request, _('Unable to set project quotas.'))
+ return True
+
+
+class UpdateProjectInfoAction(CreateProjectInfoAction):
+ enabled = forms.BooleanField(required=False, label=_("Enabled"))
+
+ class Meta:
+ name = _("Project Info")
+ slug = 'update_info'
+ help_text = _("From here you can edit the project details.")
+
+
+class UpdateProjectInfo(workflows.Step):
+ action_class = UpdateProjectInfoAction
+ depends_on = ("project_id",)
+ contributes = ("name",
+ "description",
+ "enabled")
+
+
+class UpdateProject(workflows.Workflow):
+ slug = "update_project"
+ name = _("Edit Project")
+ finalize_button_name = _("Save")
+ success_message = _('Modified project "%s".')
+ failure_message = _('Unable to modify project "%s".')
+ success_url = "horizon:admin:projects:index"
+ default_steps = (UpdateProjectInfo,
+ UpdateProjectMembers,
+ UpdateProjectQuota)
+
+ def format_status_message(self, message):
+ return message % self.context.get('name', 'unknown project')
+
+ def handle(self, request, data):
+ project_id = data['project_id']
+ # update project info
+ try:
+ api.tenant_update(request,
+ tenant_id=project_id,
+ tenant_name=data['name'],
+ description=data['description'],
+ enabled=data['enabled'])
+ except:
+ exceptions.handle(request, ignore=True)
+ return False
+
+ # update project members
+ users_to_modify = 0
+ try:
+ available_roles = api.keystone.role_list(request)
+ project_members = api.keystone.user_list(request,
+ tenant_id=project_id)
+ users_to_modify = len(project_members)
+ for user in project_members:
+ current_roles = api.roles_for_user(self.request,
+ user.id,
+ project_id)
+ for role in available_roles:
+ role_list = data["role_" + role.id]
+ if user.id in role_list:
+ if role not in current_roles:
+ # user role has changed
+ api.add_tenant_user_role(request,
+ tenant_id=project_id,
+ user_id=user.id,
+ role_id=role.id)
+ else:
+ # user role is unchanged
+ current_roles.pop(current_roles.index(role))
+ # delete user's removed roles
+ for to_delete in current_roles:
+ api.remove_tenant_user_role(request,
+ tenant_id=project_id,
+ user_id=user.id,
+ role_id=to_delete.id)
+ users_to_modify -= 1
+
+ # add new roles to project
+ for role in available_roles:
+ # count how many users may be added for exception handling
+ role_list = data["role_" + role.id]
+ users_to_modify += len(role_list)
+ for role in available_roles:
+ role_list = data["role_" + role.id]
+ users_added = 0
+ for user in role_list:
+ if not filter(lambda x: user == x.id, project_members):
+ api.add_tenant_user_role(request,
+ tenant_id=project_id,
+ user_id=user,
+ role_id=role.id)
+ users_added += 1
+ users_to_modify -= users_added
+ except:
+ exceptions.handle(request, _('Failed to modify %s project members '
+ 'and update project quotas.'
+ % users_to_modify))
+ return True
+
+ # update the project quota
+ ifcb = data['injected_file_content_bytes']
+ try:
+ api.tenant_quota_update(request,
+ project_id,
+ metadata_items=data['metadata_items'],
+ injected_file_content_bytes=ifcb,
+ volumes=data['volumes'],
+ gigabytes=data['gigabytes'],
+ ram=data['ram'],
+ floating_ips=data['floating_ips'],
+ instances=data['instances'],
+ injected_files=data['injected_files'],
+ cores=data['cores'])
+ return True
+ except:
+ exceptions.handle(request, _('Modified project information and '
+ 'members, but unable to modify '
+ 'project quotas.'))
+ return True
diff --git a/openstack_dashboard/dashboards/admin/quotas/__init__.py b/openstack_dashboard/dashboards/admin/quotas/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/quotas/__init__.py
diff --git a/openstack_dashboard/dashboards/admin/quotas/panel.py b/openstack_dashboard/dashboards/admin/quotas/panel.py
new file mode 100644
index 000000000..266f6af2b
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/quotas/panel.py
@@ -0,0 +1,33 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.admin import dashboard
+
+
+class Quotas(horizon.Panel):
+ name = _("Quotas")
+ slug = 'quotas'
+
+
+dashboard.Admin.register(Quotas)
diff --git a/openstack_dashboard/dashboards/admin/quotas/tables.py b/openstack_dashboard/dashboards/admin/quotas/tables.py
new file mode 100644
index 000000000..9ca936e36
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/quotas/tables.py
@@ -0,0 +1,38 @@
+import logging
+
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import tables
+
+
+LOG = logging.getLogger(__name__)
+
+
+class QuotaFilterAction(tables.FilterAction):
+ def filter(self, table, tenants, filter_string):
+ q = filter_string.lower()
+
+ def comp(tenant):
+ if q in tenant.name.lower():
+ return True
+ return False
+
+ return filter(comp, tenants)
+
+
+def get_quota_name(quota):
+ return quota.name.replace("_", " ").title()
+
+
+class QuotasTable(tables.DataTable):
+ name = tables.Column(get_quota_name, verbose_name=_('Quota Name'))
+ limit = tables.Column("limit", verbose_name=_('Limit'))
+
+ def get_object_id(self, obj):
+ return obj.name
+
+ class Meta:
+ name = "quotas"
+ verbose_name = _("Quotas")
+ table_actions = (QuotaFilterAction,)
+ multi_select = False
diff --git a/openstack_dashboard/dashboards/admin/quotas/templates/quotas/index.html b/openstack_dashboard/dashboards/admin/quotas/templates/quotas/index.html
new file mode 100644
index 000000000..0650cf021
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/quotas/templates/quotas/index.html
@@ -0,0 +1,13 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Quotas{% endblock %}
+
+{% block page_header %}
+ {% url horizon:admin:quotas:index as refresh_link %}
+ {# to make searchable false, just remove it from the include statement #}
+ {% include "horizon/common/_page_header.html" with title=_("Default Quotas") refresh_link=refresh_link searchable="true" %}
+{% endblock page_header %}
+
+{% block main %}
+ {{ table.render }}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/quotas/tests.py b/openstack_dashboard/dashboards/admin/quotas/tests.py
new file mode 100644
index 000000000..adcf7d8d1
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/quotas/tests.py
@@ -0,0 +1 @@
+#FIXME(gabriel): Needs tests!
diff --git a/openstack_dashboard/dashboards/admin/quotas/urls.py b/openstack_dashboard/dashboards/admin/quotas/urls.py
new file mode 100644
index 000000000..33871bce0
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/quotas/urls.py
@@ -0,0 +1,27 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import patterns, url
+
+from .views import IndexView
+
+
+urlpatterns = patterns('openstack_dashboard.dashboards.admin.quotas.views',
+ url(r'^$', IndexView.as_view(), name='index'))
diff --git a/openstack_dashboard/dashboards/admin/quotas/views.py b/openstack_dashboard/dashboards/admin/quotas/views.py
new file mode 100644
index 000000000..68d615759
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/quotas/views.py
@@ -0,0 +1,47 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.utils.translation import ugettext as _
+
+from horizon import exceptions
+from horizon import tables
+
+from openstack_dashboard import api
+from .tables import QuotasTable
+
+
+LOG = logging.getLogger(__name__)
+
+
+class IndexView(tables.DataTableView):
+ table_class = QuotasTable
+ template_name = 'admin/quotas/index.html'
+
+ def get_data(self):
+ try:
+ quota_set = api.tenant_quota_defaults(self.request,
+ self.request.user.tenant_id)
+ data = quota_set.items
+ except:
+ data = []
+ exceptions.handle(self.request, _('Unable to get quota info.'))
+ return data
diff --git a/openstack_dashboard/dashboards/admin/services/__init__.py b/openstack_dashboard/dashboards/admin/services/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/services/__init__.py
diff --git a/openstack_dashboard/dashboards/admin/services/panel.py b/openstack_dashboard/dashboards/admin/services/panel.py
new file mode 100644
index 000000000..622f37e23
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/services/panel.py
@@ -0,0 +1,33 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.admin import dashboard
+
+
+class Services(horizon.Panel):
+ name = _("Services")
+ slug = 'services'
+
+
+dashboard.Admin.register(Services)
diff --git a/openstack_dashboard/dashboards/admin/services/tables.py b/openstack_dashboard/dashboards/admin/services/tables.py
new file mode 100644
index 000000000..fd9aa8cad
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/services/tables.py
@@ -0,0 +1,50 @@
+import logging
+
+from django import template
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import tables
+
+
+LOG = logging.getLogger(__name__)
+
+
+class ServiceFilterAction(tables.FilterAction):
+ def filter(self, table, services, filter_string):
+ q = filter_string.lower()
+
+ def comp(service):
+ if q in service.type.lower():
+ return True
+ return False
+
+ return filter(comp, services)
+
+
+def get_stats(service):
+ return template.loader.render_to_string('admin/services/_stats.html',
+ {'service': service})
+
+
+def get_enabled(service, reverse=False):
+ options = ["Enabled", "Disabled"]
+ if reverse:
+ options.reverse()
+ return options[0] if not service.disabled else options[1]
+
+
+class ServicesTable(tables.DataTable):
+ id = tables.Column('id', verbose_name=_('Id'), hidden=True)
+ name = tables.Column("name", verbose_name=_('Name'))
+ service_type = tables.Column('__unicode__', verbose_name=_('Service'))
+ host = tables.Column('host', verbose_name=_('Host'))
+ enabled = tables.Column(get_enabled,
+ verbose_name=_('Enabled'),
+ status=True)
+
+ class Meta:
+ name = "services"
+ verbose_name = _("Services")
+ table_actions = (ServiceFilterAction,)
+ multi_select = False
+ status_columns = ["enabled"]
diff --git a/openstack_dashboard/dashboards/admin/services/templates/services/index.html b/openstack_dashboard/dashboards/admin/services/templates/services/index.html
new file mode 100644
index 000000000..abfba78dd
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/services/templates/services/index.html
@@ -0,0 +1,14 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Services{% endblock %}
+
+{% block page_header %}
+ {% url horizon:admin:services:index as refresh_link %}
+ {# to make searchable false, just remove it from the include statement #}
+ {% include "horizon/common/_page_header.html" with title=_("Services") refresh_link=refresh_link searchable="true" %}
+{% endblock page_header %}
+
+{% block main %}
+ {{ table.render }}
+{% endblock %}
+
diff --git a/openstack_dashboard/dashboards/admin/services/tests.py b/openstack_dashboard/dashboards/admin/services/tests.py
new file mode 100644
index 000000000..15f5fa98f
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/services/tests.py
@@ -0,0 +1,36 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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
+
+from openstack_dashboard.test import helpers as test
+
+
+INDEX_URL = reverse('horizon:admin:services:index')
+
+
+class ServicessViewTests(test.BaseAdminViewTests):
+ def test_index(self):
+ res = self.client.get(INDEX_URL)
+ self.assertTemplateUsed(res, 'admin/services/index.html')
+ self.assertQuerysetEqual(res.context['table'].data,
+ ['<Service: compute>',
+ '<Service: volume>',
+ '<Service: image>',
+ '<Service: identity (native backend)>',
+ '<Service: object-store>',
+ '<Service: network>',
+ '<Service: ec2>'])
diff --git a/openstack_dashboard/dashboards/admin/services/urls.py b/openstack_dashboard/dashboards/admin/services/urls.py
new file mode 100644
index 000000000..b5a5c9cd3
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/services/urls.py
@@ -0,0 +1,27 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import patterns, url
+
+from .views import IndexView
+
+
+urlpatterns = patterns('openstack_dashboard.dashboards.admin.services.views',
+ url(r'^$', IndexView.as_view(), name='index'))
diff --git a/openstack_dashboard/dashboards/admin/services/views.py b/openstack_dashboard/dashboards/admin/services/views.py
new file mode 100644
index 000000000..382468545
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/services/views.py
@@ -0,0 +1,41 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from horizon import tables
+
+from openstack_dashboard import api
+from .tables import ServicesTable
+
+
+LOG = logging.getLogger(__name__)
+
+
+class IndexView(tables.DataTableView):
+ table_class = ServicesTable
+ template_name = 'admin/services/index.html'
+
+ def get_data(self):
+ services = []
+ for i, service in enumerate(self.request.user.service_catalog):
+ service['id'] = i
+ services.append(api.keystone.Service(service))
+ return services
diff --git a/openstack_dashboard/dashboards/admin/users/__init__.py b/openstack_dashboard/dashboards/admin/users/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/users/__init__.py
diff --git a/openstack_dashboard/dashboards/admin/users/forms.py b/openstack_dashboard/dashboards/admin/users/forms.py
new file mode 100644
index 000000000..b6136603c
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/users/forms.py
@@ -0,0 +1,196 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.forms import ValidationError
+from django.utils.translation import force_unicode, ugettext_lazy as _
+from django.views.decorators.debug import sensitive_variables
+
+from horizon import exceptions
+from horizon import forms
+from horizon import messages
+from horizon.utils import validators
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class BaseUserForm(forms.SelfHandlingForm):
+ def __init__(self, request, *args, **kwargs):
+ super(BaseUserForm, self).__init__(request, *args, **kwargs)
+ # Populate tenant choices
+ tenant_choices = [('', _("Select a project"))]
+
+ for tenant in api.tenant_list(request, admin=True):
+ if tenant.enabled:
+ tenant_choices.append((tenant.id, tenant.name))
+ self.fields['tenant_id'].choices = tenant_choices
+
+ def clean(self):
+ '''Check to make sure password fields match.'''
+ data = super(forms.Form, self).clean()
+ if 'password' in data:
+ if data['password'] != data.get('confirm_password', None):
+ raise ValidationError(_('Passwords do not match.'))
+ return data
+
+
+ADD_PROJECT_URL = "horizon:admin:projects:create"
+
+
+class CreateUserForm(BaseUserForm):
+ name = forms.CharField(label=_("User Name"))
+ email = forms.EmailField(label=_("Email"))
+ password = forms.RegexField(
+ label=_("Password"),
+ widget=forms.PasswordInput(render_value=False),
+ regex=validators.password_validator(),
+ error_messages={'invalid': validators.password_validator_msg()})
+ confirm_password = forms.CharField(
+ label=_("Confirm Password"),
+ required=False,
+ widget=forms.PasswordInput(render_value=False))
+ tenant_id = forms.DynamicChoiceField(label=_("Primary Project"),
+ add_item_link=ADD_PROJECT_URL)
+ role_id = forms.ChoiceField(label=_("Role"))
+
+ def __init__(self, *args, **kwargs):
+ roles = kwargs.pop('roles')
+ super(CreateUserForm, self).__init__(*args, **kwargs)
+ role_choices = [(role.id, role.name) for role in roles]
+ self.fields['role_id'].choices = role_choices
+
+ # We have to protect the entire "data" dict because it contains the
+ # password and confirm_password strings.
+ @sensitive_variables('data')
+ def handle(self, request, data):
+ try:
+ LOG.info('Creating user with name "%s"' % data['name'])
+ new_user = api.user_create(request,
+ data['name'],
+ data['email'],
+ data['password'],
+ data['tenant_id'],
+ True)
+ messages.success(request,
+ _('User "%s" was successfully created.')
+ % data['name'])
+ if data['role_id']:
+ try:
+ api.add_tenant_user_role(request,
+ data['tenant_id'],
+ new_user.id,
+ data['role_id'])
+ except:
+ exceptions.handle(request,
+ _('Unable to add user'
+ 'to primary project.'))
+ return new_user
+ except:
+ exceptions.handle(request, _('Unable to create user.'))
+
+
+class UpdateUserForm(BaseUserForm):
+ id = forms.CharField(label=_("ID"), widget=forms.HiddenInput)
+ name = forms.CharField(label=_("User Name"))
+ email = forms.EmailField(label=_("Email"))
+ password = forms.RegexField(label=_("Password"),
+ widget=forms.PasswordInput(render_value=False),
+ regex=validators.password_validator(),
+ required=False,
+ error_messages={'invalid':
+ validators.password_validator_msg()})
+ confirm_password = forms.CharField(
+ label=_("Confirm Password"),
+ widget=forms.PasswordInput(render_value=False),
+ required=False)
+ tenant_id = forms.ChoiceField(label=_("Primary Project"))
+
+ def __init__(self, request, *args, **kwargs):
+ super(UpdateUserForm, self).__init__(request, *args, **kwargs)
+
+ if api.keystone_can_edit_user() is False:
+ for field in ('name', 'email', 'password', 'confirm_password'):
+ self.fields.pop(field)
+
+ # We have to protect the entire "data" dict because it contains the
+ # password and confirm_password strings.
+ @sensitive_variables('data', 'password')
+ def handle(self, request, data):
+ failed, succeeded = [], []
+ user_is_editable = api.keystone_can_edit_user()
+ user = data.pop('id')
+ tenant = data.pop('tenant_id')
+
+ if user_is_editable:
+ password = data.pop('password')
+ data.pop('confirm_password', None)
+
+ if user_is_editable:
+ # Update user details
+ msg_bits = (_('name'), _('email'))
+ try:
+ api.keystone.user_update(request, user, **data)
+ succeeded.extend(msg_bits)
+ except:
+ failed.extend(msg_bits)
+ exceptions.handle(request, ignore=True)
+
+ # Update default tenant
+ msg_bits = (_('primary project'),)
+ try:
+ api.user_update_tenant(request, user, tenant)
+ succeeded.extend(msg_bits)
+ except:
+ failed.append(msg_bits)
+ exceptions.handle(request, ignore=True)
+
+ # Check for existing roles
+ # Show a warning if no role exists for the tenant
+ user_roles = api.keystone.roles_for_user(request, user, tenant)
+ if not user_roles:
+ messages.warning(request,
+ _('The user %s has no role defined for' +
+ ' that project.')
+ % data.get('name', None))
+
+ if user_is_editable:
+ # If present, update password
+ # FIXME(gabriel): password change should be its own form and view
+ if password:
+ msg_bits = (_('password'),)
+ try:
+ api.user_update_password(request, user, password)
+ succeeded.extend(msg_bits)
+ except:
+ failed.extend(msg_bits)
+ exceptions.handle(request, ignore=True)
+
+ if succeeded:
+ messages.success(request, _('User has been updated successfully.'))
+ if failed:
+ failed = map(force_unicode, failed)
+ messages.error(request,
+ _('Unable to update %(attributes)s for the user.')
+ % {"attributes": ", ".join(failed)})
+ return True
diff --git a/openstack_dashboard/dashboards/admin/users/panel.py b/openstack_dashboard/dashboards/admin/users/panel.py
new file mode 100644
index 000000000..a813fa4ac
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/users/panel.py
@@ -0,0 +1,33 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.admin import dashboard
+
+
+class Users(horizon.Panel):
+ name = _("Users")
+ slug = 'users'
+
+
+dashboard.Admin.register(Users)
diff --git a/openstack_dashboard/dashboards/admin/users/tables.py b/openstack_dashboard/dashboards/admin/users/tables.py
new file mode 100644
index 000000000..37a756500
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/users/tables.py
@@ -0,0 +1,124 @@
+import logging
+
+from django.template import defaultfilters
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import messages
+from horizon import tables
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+ENABLE = 0
+DISABLE = 1
+
+
+class CreateUserLink(tables.LinkAction):
+ name = "create"
+ verbose_name = _("Create User")
+ url = "horizon:admin:users:create"
+ classes = ("ajax-modal", "btn-create")
+
+ def allowed(self, request, user):
+ if api.keystone_can_edit_user():
+ return True
+ return False
+
+
+class EditUserLink(tables.LinkAction):
+ name = "edit"
+ verbose_name = _("Edit")
+ url = "horizon:admin:users:update"
+ classes = ("ajax-modal", "btn-edit")
+
+
+class ToggleEnabled(tables.BatchAction):
+ name = "enable"
+ action_present = (_("Enable"), _("Disable"))
+ action_past = (_("Enabled"), _("Disabled"))
+ data_type_singular = _("User")
+ data_type_plural = _("Users")
+ classes = ("btn-enable",)
+
+ def allowed(self, request, user=None):
+ self.enabled = True
+ if not user:
+ return self.enabled
+ self.enabled = user.enabled
+ if self.enabled:
+ self.current_present_action = DISABLE
+ else:
+ self.current_present_action = ENABLE
+ return True
+
+ def update(self, request, user=None):
+ super(ToggleEnabled, self).update(request, user)
+ if user and user.id == request.user.id:
+ self.attrs["disabled"] = "disabled"
+
+ def action(self, request, obj_id):
+ if obj_id == request.user.id:
+ messages.info(request, _('You cannot disable the user you are '
+ 'currently logged in as.'))
+ return
+ if self.enabled:
+ api.keystone.user_update_enabled(request, obj_id, False)
+ self.current_past_action = DISABLE
+ else:
+ api.keystone.user_update_enabled(request, obj_id, True)
+ self.current_past_action = ENABLE
+
+
+class DeleteUsersAction(tables.DeleteAction):
+ data_type_singular = _("User")
+ data_type_plural = _("Users")
+
+ def allowed(self, request, datum):
+ if not api.keystone_can_edit_user() or \
+ (datum and datum.id == request.user.id):
+ return False
+ return True
+
+ def delete(self, request, obj_id):
+ api.keystone.user_delete(request, obj_id)
+
+
+class UserFilterAction(tables.FilterAction):
+ def filter(self, table, users, filter_string):
+ """ Really naive case-insensitive search. """
+ # FIXME(gabriel): This should be smarter. Written for demo purposes.
+ q = filter_string.lower()
+
+ def comp(user):
+ if any([q in (user.name or "").lower(),
+ q in (user.email or "").lower()]):
+ return True
+ return False
+
+ return filter(comp, users)
+
+
+class UsersTable(tables.DataTable):
+ STATUS_CHOICES = (
+ ("true", True),
+ ("false", False)
+ )
+ name = tables.Column('name', verbose_name=_('User Name'))
+ email = tables.Column('email', verbose_name=_('Email'),
+ filters=[defaultfilters.urlize])
+ # Default tenant is not returned from Keystone currently.
+ #default_tenant = tables.Column('default_tenant',
+ # verbose_name=_('Default Project'))
+ id = tables.Column('id', verbose_name=_('User ID'))
+ enabled = tables.Column('enabled', verbose_name=_('Enabled'),
+ status=True,
+ status_choices=STATUS_CHOICES,
+ empty_value="False")
+
+ class Meta:
+ name = "users"
+ verbose_name = _("Users")
+ row_actions = (EditUserLink, ToggleEnabled, DeleteUsersAction)
+ table_actions = (UserFilterAction, CreateUserLink, DeleteUsersAction)
diff --git a/openstack_dashboard/dashboards/admin/users/templates/users/_create.html b/openstack_dashboard/dashboards/admin/users/templates/users/_create.html
new file mode 100644
index 000000000..ddcdc6d56
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/users/templates/users/_create.html
@@ -0,0 +1,24 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}create_user_form{% endblock %}
+{% block form_action %}{% url horizon:admin:users:create %}{% endblock %}
+
+{% block modal-header %}{% trans "Create User" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "From here you can create a new user and assign them to a project." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create User" %}" />
+ <a href="{% url horizon:admin:users:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/users/templates/users/_update.html b/openstack_dashboard/dashboards/admin/users/templates/users/_update.html
new file mode 100644
index 000000000..9e662e6cf
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/users/templates/users/_update.html
@@ -0,0 +1,24 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}update_user_form{% endblock %}
+{% block form_action %}{% url horizon:admin:users:update user.id %}{% endblock %}
+
+{% block modal-header %}{% trans "Update User" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "From here you can edit the user's details, including their default project." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Update User" %}" />
+ <a href="{% url horizon:admin:users:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/users/templates/users/create.html b/openstack_dashboard/dashboards/admin/users/templates/users/create.html
new file mode 100644
index 000000000..6315a7546
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/users/templates/users/create.html
@@ -0,0 +1,12 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Create User{% endblock %}
+
+{% block page_header %}
+ {# to make searchable false, just remove it from the include statement #}
+ {% include "horizon/common/_page_header.html" with title=_("Create User") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'admin/users/_create.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/users/templates/users/index.html b/openstack_dashboard/dashboards/admin/users/templates/users/index.html
new file mode 100644
index 000000000..e48701aeb
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/users/templates/users/index.html
@@ -0,0 +1,13 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Users{% endblock %}
+
+{% block page_header %}
+ {% url horizon:admin:users:index as refresh_link %}
+ {# to make searchable false, just remove it from the include statement #}
+ {% include "horizon/common/_page_header.html" with title=_("Users") refresh_link=refresh_link searchable="true" %}
+{% endblock page_header %}
+
+{% block main %}
+ {{ table.render }}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/users/templates/users/update.html b/openstack_dashboard/dashboards/admin/users/templates/users/update.html
new file mode 100644
index 000000000..b28017560
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/users/templates/users/update.html
@@ -0,0 +1,12 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Update User{% endblock %}
+
+{% block page_header %}
+ {# to make searchable false, just remove it from the include statement #}
+ {% include "horizon/common/_page_header.html" with title=_("Update User") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'admin/users/_update.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/users/tests.py b/openstack_dashboard/dashboards/admin/users/tests.py
new file mode 100644
index 000000000..259a07b2d
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/users/tests.py
@@ -0,0 +1,357 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 import http
+from django.core.urlresolvers import reverse
+
+from mox import IgnoreArg, IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+USERS_INDEX_URL = reverse('horizon:admin:users:index')
+USER_CREATE_URL = reverse('horizon:admin:users:create')
+USER_UPDATE_URL = reverse('horizon:admin:users:update', args=[1])
+
+
+class UsersViewTests(test.BaseAdminViewTests):
+ @test.create_stubs({api.keystone: ('user_list',)})
+ def test_index(self):
+ api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(USERS_INDEX_URL)
+
+ self.assertTemplateUsed(res, 'admin/users/index.html')
+ self.assertItemsEqual(res.context['table'].data, self.users.list())
+
+ @test.create_stubs({api: ('user_create',
+ 'tenant_list',
+ 'add_tenant_user_role'),
+ api.keystone: ('get_default_role',
+ 'role_list')})
+ def test_create(self):
+ user = self.users.get(id="1")
+ role = self.roles.first()
+
+ api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
+ api.user_create(IgnoreArg(),
+ user.name,
+ user.email,
+ user.password,
+ self.tenant.id,
+ True).AndReturn(user)
+ api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
+ api.keystone.get_default_role(IgnoreArg()).AndReturn(role)
+ api.add_tenant_user_role(IgnoreArg(), self.tenant.id, user.id, role.id)
+
+ self.mox.ReplayAll()
+
+ formData = {'method': 'CreateUserForm',
+ 'name': user.name,
+ 'email': user.email,
+ 'password': user.password,
+ 'tenant_id': self.tenant.id,
+ 'role_id': self.roles.first().id,
+ 'confirm_password': user.password}
+ res = self.client.post(USER_CREATE_URL, formData)
+
+ self.assertNoFormErrors(res)
+ self.assertMessageCount(success=1)
+
+ @test.create_stubs({api: ('tenant_list',),
+ api.keystone: ('role_list', 'get_default_role')})
+ def test_create_with_password_mismatch(self):
+ user = self.users.get(id="1")
+
+ api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
+ api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
+ api.keystone.get_default_role(IgnoreArg()) \
+ .AndReturn(self.roles.first())
+
+ self.mox.ReplayAll()
+
+ formData = {'method': 'CreateUserForm',
+ 'name': user.name,
+ 'email': user.email,
+ 'password': user.password,
+ 'tenant_id': self.tenant.id,
+ 'role_id': self.roles.first().id,
+ 'confirm_password': "doesntmatch"}
+
+ res = self.client.post(USER_CREATE_URL, formData)
+
+ self.assertFormError(res, "form", None, ['Passwords do not match.'])
+
+ @test.create_stubs({api: ('tenant_list',),
+ api.keystone: ('role_list', 'get_default_role')})
+ def test_create_validation_for_password_too_short(self):
+ user = self.users.get(id="1")
+
+ api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
+ api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
+ api.keystone.get_default_role(IgnoreArg()) \
+ .AndReturn(self.roles.first())
+
+ self.mox.ReplayAll()
+
+ # check password min-len verification
+ formData = {'method': 'CreateUserForm',
+ 'name': user.name,
+ 'email': user.email,
+ 'password': 'four',
+ 'tenant_id': self.tenant.id,
+ 'role_id': self.roles.first().id,
+ 'confirm_password': 'four'}
+
+ res = self.client.post(USER_CREATE_URL, formData)
+
+ self.assertFormError(
+ res, "form", 'password',
+ ['Password must be between 8 and 18 characters.'])
+
+ @test.create_stubs({api: ('tenant_list',),
+ api.keystone: ('role_list', 'get_default_role')})
+ def test_create_validation_for_password_too_long(self):
+ user = self.users.get(id="1")
+
+ api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
+ api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
+ api.keystone.get_default_role(IgnoreArg()) \
+ .AndReturn(self.roles.first())
+
+ self.mox.ReplayAll()
+
+ # check password min-len verification
+ formData = {'method': 'CreateUserForm',
+ 'name': user.name,
+ 'email': user.email,
+ 'password': 'MoreThanEighteenChars',
+ 'tenant_id': self.tenant.id,
+ 'role_id': self.roles.first().id,
+ 'confirm_password': 'MoreThanEighteenChars'}
+
+ res = self.client.post(USER_CREATE_URL, formData)
+
+ self.assertFormError(
+ res, "form", 'password',
+ ['Password must be between 8 and 18 characters.'])
+
+ @test.create_stubs({api: ('user_get',
+ 'tenant_list',
+ 'user_update_tenant',
+ 'user_update_password'),
+ api.keystone: ('user_update',
+ 'roles_for_user', )})
+ def test_update(self):
+ user = self.users.get(id="1")
+
+ api.user_get(IsA(http.HttpRequest), '1',
+ admin=True).AndReturn(user)
+ api.tenant_list(IgnoreArg(),
+ admin=True).AndReturn(self.tenants.list())
+ api.keystone.user_update(IsA(http.HttpRequest),
+ user.id,
+ email=u'test@example.com',
+ name=u'test_user').AndReturn(None)
+ api.user_update_tenant(IsA(http.HttpRequest),
+ user.id,
+ self.tenant.id).AndReturn(None)
+ api.keystone.roles_for_user(IsA(http.HttpRequest),
+ user.id,
+ self.tenant.id).AndReturn(None)
+ api.user_update_password(IsA(http.HttpRequest),
+ user.id,
+ IgnoreArg()).AndReturn(None)
+
+ self.mox.ReplayAll()
+
+ formData = {'method': 'UpdateUserForm',
+ 'id': user.id,
+ 'name': user.name,
+ 'email': user.email,
+ 'password': 'normalpwd',
+ 'tenant_id': self.tenant.id,
+ 'confirm_password': 'normalpwd'}
+
+ res = self.client.post(USER_UPDATE_URL, formData)
+
+ self.assertNoFormErrors(res)
+ self.assertMessageCount(warning=1)
+
+ @test.create_stubs({api: ('user_get',
+ 'tenant_list',
+ 'user_update_tenant',
+ 'keystone_can_edit_user'),
+ api.keystone: ('roles_for_user', )})
+ def test_update_with_keystone_can_edit_user_false(self):
+ user = self.users.get(id="1")
+
+ api.user_get(IsA(http.HttpRequest),
+ '1',
+ admin=True).AndReturn(user)
+ api.tenant_list(IgnoreArg(), admin=True).AndReturn(self.tenants.list())
+ api.keystone_can_edit_user().AndReturn(False)
+ api.keystone_can_edit_user().AndReturn(False)
+ api.user_update_tenant(IsA(http.HttpRequest),
+ user.id,
+ self.tenant.id).AndReturn(None)
+ api.keystone.roles_for_user(IsA(http.HttpRequest),
+ user.id,
+ self.tenant.id).AndReturn(None)
+
+ self.mox.ReplayAll()
+
+ formData = {'method': 'UpdateUserForm',
+ 'id': user.id,
+ 'name': user.name,
+ 'tenant_id': self.tenant.id, }
+
+ res = self.client.post(USER_UPDATE_URL, formData)
+
+ self.assertNoFormErrors(res)
+ self.assertMessageCount(warning=1)
+
+ @test.create_stubs({api: ('user_get', 'tenant_list')})
+ def test_update_validation_for_password_too_short(self):
+ user = self.users.get(id="1")
+
+ api.user_get(IsA(http.HttpRequest), '1',
+ admin=True).AndReturn(user)
+ api.tenant_list(IgnoreArg(),
+ admin=True).AndReturn(self.tenants.list())
+
+ self.mox.ReplayAll()
+
+ formData = {'method': 'UpdateUserForm',
+ 'id': user.id,
+ 'name': user.name,
+ 'email': user.email,
+ 'password': 't',
+ 'tenant_id': self.tenant.id,
+ 'confirm_password': 't'}
+
+ res = self.client.post(USER_UPDATE_URL, formData)
+
+ self.assertFormError(
+ res, "form", 'password',
+ ['Password must be between 8 and 18 characters.'])
+
+ @test.create_stubs({api: ('user_get', 'tenant_list')})
+ def test_update_validation_for_password_too_long(self):
+ user = self.users.get(id="1")
+
+ api.user_get(IsA(http.HttpRequest), '1',
+ admin=True).AndReturn(user)
+ api.tenant_list(IgnoreArg(),
+ admin=True).AndReturn(self.tenants.list())
+
+ self.mox.ReplayAll()
+
+ formData = {'method': 'UpdateUserForm',
+ 'id': user.id,
+ 'name': user.name,
+ 'email': user.email,
+ 'password': 'ThisIsASuperLongPassword',
+ 'tenant_id': self.tenant.id,
+ 'confirm_password': 'ThisIsASuperLongPassword'}
+
+ res = self.client.post(USER_UPDATE_URL, formData)
+
+ self.assertFormError(
+ res, "form", 'password',
+ ['Password must be between 8 and 18 characters.'])
+
+ @test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')})
+ def test_enable_user(self):
+ user = self.users.get(id="2")
+ user.enabled = False
+ api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
+ api.keystone.user_update_enabled(IgnoreArg(),
+ user.id,
+ True).AndReturn(user)
+
+ self.mox.ReplayAll()
+
+ formData = {'action': 'users__enable__%s' % user.id}
+ res = self.client.post(USERS_INDEX_URL, formData)
+
+ self.assertRedirectsNoFollow(res, USERS_INDEX_URL)
+
+ @test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')})
+ def test_disable_user(self):
+ user = self.users.get(id="2")
+ self.assertTrue(user.enabled)
+
+ api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
+ api.keystone.user_update_enabled(IgnoreArg(),
+ user.id,
+ False).AndReturn(user)
+
+ self.mox.ReplayAll()
+
+ formData = {'action': 'users__enable__%s' % user.id}
+ res = self.client.post(USERS_INDEX_URL, formData)
+
+ self.assertRedirectsNoFollow(res, USERS_INDEX_URL)
+
+ @test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')})
+ def test_enable_disable_user_exception(self):
+ user = self.users.get(id="2")
+ user.enabled = False
+ api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
+ api.keystone.user_update_enabled(IgnoreArg(), user.id, True) \
+ .AndRaise(self.exceptions.keystone)
+ self.mox.ReplayAll()
+
+ formData = {'action': 'users__enable__%s' % user.id}
+ res = self.client.post(USERS_INDEX_URL, formData)
+
+ self.assertRedirectsNoFollow(res, USERS_INDEX_URL)
+
+ @test.create_stubs({api.keystone: ('user_list',)})
+ def test_disabling_current_user(self):
+ for i in range(0, 2):
+ api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
+
+ self.mox.ReplayAll()
+
+ formData = {'action': 'users__enable__%s' % self.request.user.id}
+ res = self.client.post(USERS_INDEX_URL, formData, follow=True)
+
+ self.assertEqual(list(res.context['messages'])[0].message,
+ u'You cannot disable the user you are currently '
+ u'logged in as.')
+
+ @test.create_stubs({api.keystone: ('user_list',)})
+ def test_delete_user_with_improper_permissions(self):
+ for i in range(0, 2):
+ api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
+
+ self.mox.ReplayAll()
+
+ formData = {'action': 'users__delete__%s' % self.request.user.id}
+ res = self.client.post(USERS_INDEX_URL, formData, follow=True)
+
+ self.assertEqual(list(res.context['messages'])[0].message,
+ u'You do not have permission to delete user: %s'
+ % self.request.user.username)
diff --git a/openstack_dashboard/dashboards/admin/users/urls.py b/openstack_dashboard/dashboards/admin/users/urls.py
new file mode 100644
index 000000000..7daf96933
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/users/urls.py
@@ -0,0 +1,28 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import patterns, url
+
+from .views import IndexView, CreateView, UpdateView
+
+urlpatterns = patterns('openstack_dashboard.dashboards.admin.users.views',
+ url(r'^$', IndexView.as_view(), name='index'),
+ url(r'^(?P<user_id>[^/]+)/update/$', UpdateView.as_view(), name='update'),
+ url(r'^create/$', CreateView.as_view(), name='create'))
diff --git a/openstack_dashboard/dashboards/admin/users/views.py b/openstack_dashboard/dashboards/admin/users/views.py
new file mode 100644
index 000000000..c6c48ae63
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/users/views.py
@@ -0,0 +1,112 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 operator
+
+from django.core.urlresolvers import reverse, reverse_lazy
+from django.utils.decorators import method_decorator
+from django.utils.translation import ugettext_lazy as _
+from django.views.decorators.debug import sensitive_post_parameters
+
+from horizon import exceptions
+from horizon import forms
+from horizon import tables
+
+from openstack_dashboard import api
+from .forms import CreateUserForm, UpdateUserForm
+from .tables import UsersTable
+
+
+class IndexView(tables.DataTableView):
+ table_class = UsersTable
+ template_name = 'admin/users/index.html'
+
+ def get_data(self):
+ users = []
+ try:
+ users = api.keystone.user_list(self.request)
+ except:
+ exceptions.handle(self.request,
+ _('Unable to retrieve user list.'))
+ return users
+
+
+class UpdateView(forms.ModalFormView):
+ form_class = UpdateUserForm
+ template_name = 'admin/users/update.html'
+ success_url = reverse_lazy('horizon:admin:users:index')
+
+ @method_decorator(sensitive_post_parameters('password',
+ 'confirm_password'))
+ def dispatch(self, *args, **kwargs):
+ return super(UpdateView, self).dispatch(*args, **kwargs)
+
+ def get_object(self):
+ if not hasattr(self, "_object"):
+ try:
+ self._object = api.user_get(self.request,
+ self.kwargs['user_id'],
+ admin=True)
+ except:
+ redirect = reverse("horizon:admin:users:index")
+ exceptions.handle(self.request,
+ _('Unable to update user.'),
+ redirect=redirect)
+ return self._object
+
+ def get_context_data(self, **kwargs):
+ context = super(UpdateView, self).get_context_data(**kwargs)
+ context['user'] = self.get_object()
+ return context
+
+ def get_initial(self):
+ user = self.get_object()
+ return {'id': user.id,
+ 'name': user.name,
+ 'tenant_id': getattr(user, 'tenantId', None),
+ 'email': user.email}
+
+
+class CreateView(forms.ModalFormView):
+ form_class = CreateUserForm
+ template_name = 'admin/users/create.html'
+ success_url = reverse_lazy('horizon:admin:users:index')
+
+ @method_decorator(sensitive_post_parameters('password',
+ 'confirm_password'))
+ def dispatch(self, *args, **kwargs):
+ return super(CreateView, self).dispatch(*args, **kwargs)
+
+ def get_form_kwargs(self):
+ kwargs = super(CreateView, self).get_form_kwargs()
+ try:
+ roles = api.keystone.role_list(self.request)
+ except:
+ redirect = reverse("horizon:admin:users:index")
+ exceptions.handle(self.request,
+ _("Unable to retrieve user roles."),
+ redirect=redirect)
+ roles.sort(key=operator.attrgetter("id"))
+ kwargs['roles'] = roles
+ return kwargs
+
+ def get_initial(self):
+ default_role = api.keystone.get_default_role(self.request)
+ return {'role_id': getattr(default_role, "id", None)}
diff --git a/openstack_dashboard/dashboards/admin/volumes/__init__.py b/openstack_dashboard/dashboards/admin/volumes/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/volumes/__init__.py
diff --git a/openstack_dashboard/dashboards/admin/volumes/panel.py b/openstack_dashboard/dashboards/admin/volumes/panel.py
new file mode 100644
index 000000000..0a0eba498
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/volumes/panel.py
@@ -0,0 +1,14 @@
+from django.utils.translation import ugettext_lazy as _
+
+import horizon
+
+from openstack_dashboard.dashboards.admin import dashboard
+
+
+class Volumes(horizon.Panel):
+ name = _("Volumes")
+ slug = "volumes"
+ permissions = ('openstack.services.volume',)
+
+
+dashboard.Admin.register(Volumes)
diff --git a/openstack_dashboard/dashboards/admin/volumes/tables.py b/openstack_dashboard/dashboards/admin/volumes/tables.py
new file mode 100644
index 000000000..133743695
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/volumes/tables.py
@@ -0,0 +1,19 @@
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import tables
+from openstack_dashboard.dashboards.project.volumes.tables import (UpdateRow,
+ VolumesTable as _VolumesTable, DeleteVolume)
+
+
+class VolumesTable(_VolumesTable):
+ name = tables.Column("display_name",
+ verbose_name=_("Name"),
+ link="horizon:admin:volumes:detail")
+
+ class Meta:
+ name = "volumes"
+ verbose_name = _("Volumes")
+ status_columns = ["status"]
+ row_class = UpdateRow
+ table_actions = (DeleteVolume,)
+ row_actions = (DeleteVolume,)
diff --git a/openstack_dashboard/dashboards/admin/volumes/templates/volumes/detail.html b/openstack_dashboard/dashboards/admin/volumes/templates/volumes/detail.html
new file mode 100644
index 000000000..9dbbd4084
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/volumes/templates/volumes/detail.html
@@ -0,0 +1,15 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Volume Details" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Volume Detail") %}
+{% endblock page_header %}
+
+{% block main %}
+<div class="row-fluid">
+ <div class="span12">
+ {{ tab_group.render }}
+ </div>
+</div>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/admin/volumes/templates/volumes/index.html b/openstack_dashboard/dashboards/admin/volumes/templates/volumes/index.html
new file mode 100644
index 000000000..4079378aa
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/volumes/templates/volumes/index.html
@@ -0,0 +1,13 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Volumes" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Volumes") %}
+{% endblock page_header %}
+
+{% block main %}
+ {{ table.render }}
+{% endblock %}
+
+
diff --git a/openstack_dashboard/dashboards/admin/volumes/tests.py b/openstack_dashboard/dashboards/admin/volumes/tests.py
new file mode 100644
index 000000000..fd0dafa58
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/volumes/tests.py
@@ -0,0 +1,39 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 import http
+from django.core.urlresolvers import reverse
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+class VolumeTests(test.BaseAdminViewTests):
+ @test.create_stubs({api: ('server_list', 'volume_list',)})
+ def test_index(self):
+ api.volume_list(IsA(http.HttpRequest), search_opts={
+ 'all_tenants': 1}).AndReturn(self.volumes.list())
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:admin:volumes:index'))
+
+ self.assertTemplateUsed(res, 'admin/volumes/index.html')
+ volumes = res.context['volumes_table'].data
+
+ self.assertItemsEqual(volumes, self.volumes.list())
diff --git a/openstack_dashboard/dashboards/admin/volumes/urls.py b/openstack_dashboard/dashboards/admin/volumes/urls.py
new file mode 100644
index 000000000..f42c753f0
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/volumes/urls.py
@@ -0,0 +1,8 @@
+from django.conf.urls.defaults import patterns, url
+
+from .views import IndexView, DetailView
+
+urlpatterns = patterns('',
+ url(r'^$', IndexView.as_view(), name='index'),
+ url(r'^(?P<volume_id>[^/]+)/$', DetailView.as_view(), name='detail'),
+)
diff --git a/openstack_dashboard/dashboards/admin/volumes/views.py b/openstack_dashboard/dashboards/admin/volumes/views.py
new file mode 100644
index 000000000..5682aa8a9
--- /dev/null
+++ b/openstack_dashboard/dashboards/admin/volumes/views.py
@@ -0,0 +1,39 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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.
+
+"""
+Admin views for managing volumes.
+"""
+
+from openstack_dashboard.dashboards.project.volumes.views import \
+ IndexView as _IndexView, DetailView as _DetailView
+from .tables import VolumesTable
+
+
+class IndexView(_IndexView):
+ table_class = VolumesTable
+ template_name = "admin/volumes/index.html"
+
+ def get_data(self):
+ volumes = self._get_volumes(search_opts={'all_tenants': 1})
+ instances = self._get_instances()
+ self._set_id_if_nameless(volumes, instances)
+ self._set_attachments_string(volumes, instances)
+ return volumes
+
+
+class DetailView(_DetailView):
+ template_name = "admin/volumes/detail.html"
diff --git a/openstack_dashboard/dashboards/project/__init__.py b/openstack_dashboard/dashboards/project/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/__init__.py
diff --git a/openstack_dashboard/dashboards/project/access_and_security/__init__.py b/openstack_dashboard/dashboards/project/access_and_security/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/__init__.py
diff --git a/openstack_dashboard/dashboards/project/access_and_security/floating_ips/__init__.py b/openstack_dashboard/dashboards/project/access_and_security/floating_ips/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/floating_ips/__init__.py
diff --git a/openstack_dashboard/dashboards/project/access_and_security/floating_ips/forms.py b/openstack_dashboard/dashboards/project/access_and_security/floating_ips/forms.py
new file mode 100644
index 000000000..94f16464a
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/floating_ips/forms.py
@@ -0,0 +1,47 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+# Copyright (c) 2012 X.commerce, a business unit of eBay Inc.
+#
+# 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 _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import messages
+
+from openstack_dashboard import api
+
+
+class FloatingIpAllocate(forms.SelfHandlingForm):
+ pool = forms.ChoiceField(label=_("Pool"))
+
+ def __init__(self, *args, **kwargs):
+ super(FloatingIpAllocate, self).__init__(*args, **kwargs)
+ floating_pool_list = kwargs.get('initial', {}).get('pool_list', [])
+ self.fields['pool'].choices = floating_pool_list
+
+ def handle(self, request, data):
+ try:
+ fip = api.tenant_floating_ip_allocate(request, pool=data['pool'])
+ messages.success(request,
+ _('Allocated Floating IP %(ip)s.')
+ % {"ip": fip.ip})
+ return fip
+ except:
+ exceptions.handle(request, _('Unable to allocate Floating IP.'))
diff --git a/openstack_dashboard/dashboards/project/access_and_security/floating_ips/tables.py b/openstack_dashboard/dashboards/project/access_and_security/floating_ips/tables.py
new file mode 100644
index 000000000..788c3730b
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/floating_ips/tables.py
@@ -0,0 +1,130 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+# Copyright (c) 2012 X.commerce, a business unit of eBay Inc.
+#
+# 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 logging
+
+from django import shortcuts
+from django.core import urlresolvers
+from django.utils.http import urlencode
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import messages
+from horizon import tables
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class AllocateIP(tables.LinkAction):
+ name = "allocate"
+ verbose_name = _("Allocate IP To Project")
+ classes = ("ajax-modal", "btn-allocate")
+ url = "horizon:project:access_and_security:floating_ips:allocate"
+
+ def single(self, data_table, request, *args):
+ return shortcuts.redirect('horizon:project:access_and_security:index')
+
+
+class ReleaseIPs(tables.BatchAction):
+ name = "release"
+ action_present = _("Release")
+ action_past = _("Released")
+ data_type_singular = _("Floating IP")
+ data_type_plural = _("Floating IPs")
+ classes = ('btn-danger', 'btn-release')
+
+ def action(self, request, obj_id):
+ api.tenant_floating_ip_release(request, obj_id)
+
+
+class AssociateIP(tables.LinkAction):
+ name = "associate"
+ verbose_name = _("Associate Floating IP")
+ url = "horizon:project:access_and_security:floating_ips:associate"
+ classes = ("ajax-modal", "btn-associate")
+
+ def allowed(self, request, fip):
+ if fip.instance_id:
+ return False
+ return True
+
+ def get_link_url(self, datum):
+ base_url = urlresolvers.reverse(self.url)
+ params = urlencode({"ip_id": self.table.get_object_id(datum)})
+ return "?".join([base_url, params])
+
+
+class DisassociateIP(tables.Action):
+ name = "disassociate"
+ verbose_name = _("Disassociate Floating IP")
+ classes = ("btn-disassociate", "btn-danger")
+
+ def allowed(self, request, fip):
+ if fip.instance_id:
+ return True
+ return False
+
+ def single(self, table, request, obj_id):
+ try:
+ fip = table.get_object_by_id(int(obj_id))
+ api.server_remove_floating_ip(request, fip.instance_id, fip.id)
+ LOG.info('Disassociating Floating IP "%s".' % obj_id)
+ messages.success(request,
+ _('Successfully disassociated Floating IP: %s')
+ % fip.ip)
+ except:
+ exceptions.handle(request,
+ _('Unable to disassociate floating IP.'))
+ return shortcuts.redirect('horizon:project:access_and_security:index')
+
+
+def get_instance_info(instance):
+ return getattr(instance, "instance_name", None)
+
+
+def get_instance_link(datum):
+ view = "horizon:project:instances:detail"
+ if datum.instance_id:
+ return urlresolvers.reverse(view, args=(datum.instance_id,))
+ else:
+ return None
+
+
+class FloatingIPsTable(tables.DataTable):
+ ip = tables.Column("ip", verbose_name=_("IP Address"))
+ instance = tables.Column(get_instance_info,
+ link=get_instance_link,
+ verbose_name=_("Instance"),
+ empty_value="-")
+ pool = tables.Column("pool",
+ verbose_name=_("Floating IP Pool"),
+ empty_value="-")
+
+ def sanitize_id(self, obj_id):
+ return int(obj_id)
+
+ def get_object_display(self, datum):
+ return datum.ip
+
+ class Meta:
+ name = "floating_ips"
+ verbose_name = _("Floating IPs")
+ table_actions = (AllocateIP, ReleaseIPs)
+ row_actions = (AssociateIP, DisassociateIP, ReleaseIPs)
diff --git a/openstack_dashboard/dashboards/project/access_and_security/floating_ips/tests.py b/openstack_dashboard/dashboards/project/access_and_security/floating_ips/tests.py
new file mode 100644
index 000000000..8daddbf79
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/floating_ips/tests.py
@@ -0,0 +1,177 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+# Copyright (c) 2012 X.commerce, a business unit of eBay Inc.
+#
+# 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 import http
+from django.core.urlresolvers import reverse
+
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+INDEX_URL = reverse('horizon:project:access_and_security:index')
+NAMESPACE = "horizon:project:access_and_security:floating_ips"
+
+
+class FloatingIpViewTests(test.TestCase):
+ def test_associate(self):
+ self.mox.StubOutWithMock(api.nova, 'server_list')
+ self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
+ api.nova.server_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.servers.list())
+ api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.floating_ips.list())
+ self.mox.ReplayAll()
+
+ url = reverse('%s:associate' % NAMESPACE)
+ res = self.client.get(url)
+ self.assertTemplateUsed(res,
+ 'project/access_and_security/floating_ips/associate.html')
+ workflow = res.context['workflow']
+ choices = dict(workflow.steps[0].action.fields['ip_id'].choices)
+ # Verify that our "associated" floating IP isn't in the choices list.
+ self.assertTrue(self.floating_ips.get(id=1) not in choices)
+
+ def test_associate_post(self):
+ floating_ip = self.floating_ips.get(id=2)
+ server = self.servers.first()
+ self.mox.StubOutWithMock(api.nova, 'server_add_floating_ip')
+ self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
+ self.mox.StubOutWithMock(api.nova, 'server_list')
+
+ api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.floating_ips.list())
+ api.nova.server_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.servers.list())
+ api.nova.server_add_floating_ip(IsA(http.HttpRequest),
+ server.id,
+ floating_ip.id)
+ self.mox.ReplayAll()
+
+ form_data = {'instance_id': server.id,
+ 'ip_id': floating_ip.id}
+ url = reverse('%s:associate' % NAMESPACE)
+ res = self.client.post(url, form_data)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ def test_associate_post_with_redirect(self):
+ floating_ip = self.floating_ips.get(id=2)
+ server = self.servers.first()
+ self.mox.StubOutWithMock(api.nova, 'server_add_floating_ip')
+ self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
+ self.mox.StubOutWithMock(api.nova, 'server_list')
+
+ api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.floating_ips.list())
+ api.nova.server_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.servers.list())
+ api.nova.server_add_floating_ip(IsA(http.HttpRequest),
+ server.id,
+ floating_ip.id)
+ self.mox.ReplayAll()
+
+ form_data = {'instance_id': server.id,
+ 'ip_id': floating_ip.id}
+ url = reverse('%s:associate' % NAMESPACE)
+ next = reverse("horizon:project:instances:index")
+ res = self.client.post("%s?next=%s" % (url, next), form_data)
+ self.assertRedirectsNoFollow(res, next)
+
+ def test_associate_post_with_exception(self):
+ floating_ip = self.floating_ips.get(id=2)
+ server = self.servers.first()
+ self.mox.StubOutWithMock(api.nova, 'server_add_floating_ip')
+ self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
+ self.mox.StubOutWithMock(api.nova, 'server_list')
+
+ api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.floating_ips.list())
+ api.nova.server_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.servers.list())
+ api.nova.server_add_floating_ip(IsA(http.HttpRequest),
+ server.id,
+ floating_ip.id) \
+ .AndRaise(self.exceptions.nova)
+ self.mox.ReplayAll()
+
+ form_data = {'instance_id': server.id,
+ 'ip_id': floating_ip.id}
+ url = reverse('%s:associate' % NAMESPACE)
+ res = self.client.post(url, form_data)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ def test_disassociate_post(self):
+ floating_ip = self.floating_ips.first()
+ server = self.servers.first()
+ self.mox.StubOutWithMock(api.nova, 'keypair_list')
+ self.mox.StubOutWithMock(api, 'security_group_list')
+ self.mox.StubOutWithMock(api, 'tenant_floating_ip_list')
+ self.mox.StubOutWithMock(api, 'tenant_floating_ip_get')
+ self.mox.StubOutWithMock(api, 'server_remove_floating_ip')
+ self.mox.StubOutWithMock(api.nova, 'server_list')
+
+ api.nova.server_list(IsA(http.HttpRequest),
+ all_tenants=True).AndReturn(self.servers.list())
+ api.nova.keypair_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.keypairs.list())
+ api.security_group_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.security_groups.list())
+ api.tenant_floating_ip_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.floating_ips.list())
+ api.server_remove_floating_ip(IsA(http.HttpRequest),
+ server.id,
+ floating_ip.id)
+ self.mox.ReplayAll()
+
+ action = "floating_ips__disassociate__%s" % floating_ip.id
+ res = self.client.post(INDEX_URL, {"action": action})
+ self.assertMessageCount(success=1)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ def test_disassociate_post_with_exception(self):
+ floating_ip = self.floating_ips.first()
+ server = self.servers.first()
+ self.mox.StubOutWithMock(api.nova, 'keypair_list')
+ self.mox.StubOutWithMock(api, 'security_group_list')
+ self.mox.StubOutWithMock(api, 'tenant_floating_ip_list')
+ self.mox.StubOutWithMock(api, 'tenant_floating_ip_get')
+ self.mox.StubOutWithMock(api, 'server_remove_floating_ip')
+ self.mox.StubOutWithMock(api.nova, 'server_list')
+
+ api.nova.server_list(IsA(http.HttpRequest),
+ all_tenants=True).AndReturn(self.servers.list())
+ api.nova.keypair_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.keypairs.list())
+ api.security_group_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.security_groups.list())
+ api.tenant_floating_ip_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.floating_ips.list())
+
+ api.server_remove_floating_ip(IsA(http.HttpRequest),
+ server.id,
+ floating_ip.id) \
+ .AndRaise(self.exceptions.nova)
+ self.mox.ReplayAll()
+
+ action = "floating_ips__disassociate__%s" % floating_ip.id
+ res = self.client.post(INDEX_URL, {"action": action})
+ self.assertRedirectsNoFollow(res, INDEX_URL)
diff --git a/openstack_dashboard/dashboards/project/access_and_security/floating_ips/urls.py b/openstack_dashboard/dashboards/project/access_and_security/floating_ips/urls.py
new file mode 100644
index 000000000..cc8da951a
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/floating_ips/urls.py
@@ -0,0 +1,29 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import patterns, url
+
+from .views import AssociateView, AllocateView
+
+
+urlpatterns = patterns('',
+ url(r'^associate/$', AssociateView.as_view(), name='associate'),
+ url(r'^allocate/$', AllocateView.as_view(), name='allocate')
+)
diff --git a/openstack_dashboard/dashboards/project/access_and_security/floating_ips/views.py b/openstack_dashboard/dashboards/project/access_and_security/floating_ips/views.py
new file mode 100644
index 000000000..350110b52
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/floating_ips/views.py
@@ -0,0 +1,69 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+# Copyright (c) 2012 X.commerce, a business unit of eBay Inc.
+#
+# 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.
+
+"""
+Views for managing floating IPs.
+"""
+
+from django.core.urlresolvers import reverse_lazy
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import workflows
+
+from openstack_dashboard import api
+from .forms import FloatingIpAllocate
+from .workflows import IPAssociationWorkflow
+
+
+class AssociateView(workflows.WorkflowView):
+ workflow_class = IPAssociationWorkflow
+ template_name = "project/access_and_security/floating_ips/associate.html"
+
+
+class AllocateView(forms.ModalFormView):
+ form_class = FloatingIpAllocate
+ template_name = 'project/access_and_security/floating_ips/allocate.html'
+ success_url = reverse_lazy('horizon:project:access_and_security:index')
+
+ def get_object_display(self, obj):
+ return obj.ip
+
+ def get_context_data(self, **kwargs):
+ context = super(AllocateView, self).get_context_data(**kwargs)
+ try:
+ context['usages'] = api.tenant_quota_usages(self.request)
+ except:
+ exceptions.handle(self.request)
+ return context
+
+ def get_initial(self):
+ try:
+ pools = api.floating_ip_pools_list(self.request)
+ except:
+ pools = []
+ exceptions.handle(self.request,
+ _("Unable to retrieve floating IP pools."))
+ pool_list = [(pool.name, pool.name) for pool in pools]
+ if not pool_list:
+ pool_list = [(None, _("No floating IP pools available."))]
+ return {'pool_list': pool_list}
diff --git a/openstack_dashboard/dashboards/project/access_and_security/floating_ips/workflows.py b/openstack_dashboard/dashboards/project/access_and_security/floating_ips/workflows.py
new file mode 100644
index 000000000..1abf670ef
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/floating_ips/workflows.py
@@ -0,0 +1,115 @@
+
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+
+# 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
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import workflows
+from horizon import forms
+
+from openstack_dashboard import api
+
+
+ALLOCATE_URL = "horizon:project:access_and_security:floating_ips:allocate"
+
+
+class AssociateIPAction(workflows.Action):
+ ip_id = forms.DynamicTypedChoiceField(label=_("IP Address"),
+ coerce=int,
+ empty_value=None,
+ add_item_link=ALLOCATE_URL)
+ instance_id = forms.ChoiceField(label=_("Instance"))
+
+ class Meta:
+ name = _("IP Address")
+ help_text = _("Select the IP address you wish to associate with "
+ "the selected instance.")
+
+ def populate_ip_id_choices(self, request, context):
+ try:
+ ips = api.nova.tenant_floating_ip_list(self.request)
+ except:
+ redirect = reverse('horizon:project:access_and_security:index')
+ exceptions.handle(self.request,
+ _('Unable to retrieve floating IP addresses.'),
+ redirect=redirect)
+ options = sorted([(ip.id, ip.ip) for ip in ips if not ip.instance_id])
+ if options:
+ options.insert(0, ("", _("Select an IP address")))
+ else:
+ options = [("", _("No IP addresses available"))]
+
+ return options
+
+ def populate_instance_id_choices(self, request, context):
+ try:
+ servers = api.nova.server_list(self.request)
+ except:
+ redirect = reverse('horizon:project:access_and_security:index')
+ exceptions.handle(self.request,
+ _('Unable to retrieve instance list.'),
+ redirect=redirect)
+ instances = []
+ for server in servers:
+ server_name = "%s (%s)" % (server.name, server.id)
+ instances.append((server.id, server_name))
+
+ # Sort instances for easy browsing
+ instances = sorted(instances, key=lambda x: x[1])
+
+ if instances:
+ instances.insert(0, ("", _("Select an instance")))
+ else:
+ instances = (("", _("No instances available")),)
+ return instances
+
+
+class AssociateIP(workflows.Step):
+ action_class = AssociateIPAction
+ contributes = ("ip_id", "instance_id", "ip_address")
+
+ def contribute(self, data, context):
+ context = super(AssociateIP, self).contribute(data, context)
+ ip_id = data.get('ip_id', None)
+ if ip_id:
+ ip_choices = dict(self.action.fields['ip_id'].choices)
+ context["ip_address"] = ip_choices.get(ip_id, None)
+ return context
+
+
+class IPAssociationWorkflow(workflows.Workflow):
+ slug = "ip_association"
+ name = _("Manage Floating IP Associations")
+ finalize_button_name = _("Associate")
+ success_message = _('IP address %s associated.')
+ failure_message = _('Unable to associate IP address %s.')
+ success_url = "horizon:project:access_and_security:index"
+ default_steps = (AssociateIP,)
+
+ def format_status_message(self, message):
+ return message % self.context.get('ip_address', 'unknown IP address')
+
+ def handle(self, request, data):
+ try:
+ api.nova.server_add_floating_ip(request,
+ data['instance_id'],
+ data['ip_id'])
+ except:
+ exceptions.handle(request)
+ return False
+ return True
diff --git a/openstack_dashboard/dashboards/project/access_and_security/keypairs/__init__.py b/openstack_dashboard/dashboards/project/access_and_security/keypairs/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/keypairs/__init__.py
diff --git a/openstack_dashboard/dashboards/project/access_and_security/keypairs/forms.py b/openstack_dashboard/dashboards/project/access_and_security/keypairs/forms.py
new file mode 100644
index 000000000..0a5d45e0d
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/keypairs/forms.py
@@ -0,0 +1,66 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 re
+
+from django.core import validators
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import messages
+
+from openstack_dashboard import api
+
+
+NEW_LINES = re.compile(r"\r|\n")
+
+
+class CreateKeypair(forms.SelfHandlingForm):
+ name = forms.CharField(max_length="20",
+ label=_("Keypair Name"),
+ validators=[validators.validate_slug],
+ error_messages={'invalid': _('Keypair names may '
+ 'only contain letters, numbers, underscores '
+ 'and hyphens.')})
+
+ def handle(self, request, data):
+ return True # We just redirect to the download view.
+
+
+class ImportKeypair(forms.SelfHandlingForm):
+ name = forms.CharField(max_length="20", label=_("Keypair Name"),
+ validators=[validators.RegexValidator('\w+')])
+ public_key = forms.CharField(label=_("Public Key"), widget=forms.Textarea)
+
+ def handle(self, request, data):
+ try:
+ # Remove any new lines in the public key
+ data['public_key'] = NEW_LINES.sub("", data['public_key'])
+ keypair = api.keypair_import(request,
+ data['name'],
+ data['public_key'])
+ messages.success(request, _('Successfully imported public key: %s')
+ % data['name'])
+ return keypair
+ except:
+ exceptions.handle(request, ignore=True)
+ self.api_error(_('Unable to import keypair.'))
+ return False
diff --git a/openstack_dashboard/dashboards/project/access_and_security/keypairs/tables.py b/openstack_dashboard/dashboards/project/access_and_security/keypairs/tables.py
new file mode 100644
index 000000000..fdec467d3
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/keypairs/tables.py
@@ -0,0 +1,62 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import tables
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class DeleteKeyPairs(tables.DeleteAction):
+ data_type_singular = _("Keypair")
+ data_type_plural = _("Keypairs")
+
+ def delete(self, request, obj_id):
+ api.nova.keypair_delete(request, obj_id)
+
+
+class ImportKeyPair(tables.LinkAction):
+ name = "import"
+ verbose_name = _("Import Keypair")
+ url = "horizon:project:access_and_security:keypairs:import"
+ classes = ("ajax-modal", "btn-upload")
+
+
+class CreateKeyPair(tables.LinkAction):
+ name = "create"
+ verbose_name = _("Create Keypair")
+ url = "horizon:project:access_and_security:keypairs:create"
+ classes = ("ajax-modal", "btn-create")
+
+
+class KeypairsTable(tables.DataTable):
+ name = tables.Column("name", verbose_name=_("Keypair Name"))
+ fingerprint = tables.Column("fingerprint", verbose_name=_("Fingerprint"))
+
+ def get_object_id(self, keypair):
+ return keypair.name
+
+ class Meta:
+ name = "keypairs"
+ verbose_name = _("Keypairs")
+ table_actions = (CreateKeyPair, ImportKeyPair, DeleteKeyPairs,)
+ row_actions = (DeleteKeyPairs,)
diff --git a/openstack_dashboard/dashboards/project/access_and_security/keypairs/tests.py b/openstack_dashboard/dashboards/project/access_and_security/keypairs/tests.py
new file mode 100644
index 000000000..60afd5b76
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/keypairs/tests.py
@@ -0,0 +1,163 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 import http
+from django.core.urlresolvers import reverse
+
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+INDEX_VIEW_URL = reverse('horizon:project:access_and_security:index')
+
+
+class KeyPairViewTests(test.TestCase):
+ def test_delete_keypair(self):
+ keypair = self.keypairs.first()
+
+ self.mox.StubOutWithMock(api.nova, 'keypair_list')
+ self.mox.StubOutWithMock(api.nova, 'keypair_delete')
+ self.mox.StubOutWithMock(api, 'security_group_list')
+ self.mox.StubOutWithMock(api, 'tenant_floating_ip_list')
+ self.mox.StubOutWithMock(api.nova, 'server_list')
+
+ api.nova.server_list(IsA(http.HttpRequest),
+ all_tenants=True).AndReturn(self.servers.list())
+ api.security_group_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.security_groups.list())
+ api.tenant_floating_ip_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.floating_ips.list())
+ api.nova.keypair_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.keypairs.list())
+ api.nova.keypair_delete(IsA(http.HttpRequest), keypair.name)
+ self.mox.ReplayAll()
+
+ formData = {'action': 'keypairs__delete__%s' % keypair.name}
+ res = self.client.post(INDEX_VIEW_URL, formData)
+ self.assertRedirectsNoFollow(res, INDEX_VIEW_URL)
+
+ def test_delete_keypair_exception(self):
+ keypair = self.keypairs.first()
+ self.mox.StubOutWithMock(api.nova, 'keypair_list')
+ self.mox.StubOutWithMock(api.nova, 'keypair_delete')
+ self.mox.StubOutWithMock(api, 'security_group_list')
+ self.mox.StubOutWithMock(api, 'tenant_floating_ip_list')
+ self.mox.StubOutWithMock(api.nova, 'server_list')
+
+ api.nova.server_list(IsA(http.HttpRequest),
+ all_tenants=True).AndReturn(self.servers.list())
+ api.security_group_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.security_groups.list())
+ api.tenant_floating_ip_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.floating_ips.list())
+ api.nova.keypair_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.keypairs.list())
+ api.nova.keypair_delete(IsA(http.HttpRequest), keypair.name) \
+ .AndRaise(self.exceptions.nova)
+ self.mox.ReplayAll()
+
+ formData = {'action': 'keypairs__delete__%s' % keypair.name}
+ res = self.client.post(INDEX_VIEW_URL, formData)
+ self.assertRedirectsNoFollow(res, INDEX_VIEW_URL)
+
+ def test_create_keypair_get(self):
+ res = self.client.get(
+ reverse('horizon:project:access_and_security:keypairs:create'))
+ self.assertTemplateUsed(res,
+ 'project/access_and_security/keypairs/create.html')
+
+ def test_download_keypair_get(self):
+ keypair_name = "keypair"
+ context = {'keypair_name': keypair_name}
+ url = reverse('horizon:project:access_and_security:keypairs:download',
+ kwargs={'keypair_name': keypair_name})
+ res = self.client.get(url, context)
+ self.assertTemplateUsed(
+ res, 'project/access_and_security/keypairs/download.html')
+
+ def test_generate_keypair_get(self):
+ keypair = self.keypairs.first()
+ keypair.private_key = "secret"
+
+ self.mox.StubOutWithMock(api, 'keypair_create')
+ api.keypair_create(IsA(http.HttpRequest),
+ keypair.name).AndReturn(keypair)
+ self.mox.ReplayAll()
+
+ context = {'keypair_name': keypair.name}
+ url = reverse('horizon:project:access_and_security:keypairs:generate',
+ kwargs={'keypair_name': keypair.name})
+ res = self.client.get(url, context)
+
+ self.assertTrue(res.has_header('content-disposition'))
+
+ @test.create_stubs({api: ("keypair_import",)})
+ def test_import_keypair(self):
+ key1_name = "new key pair"
+ public_key = "ssh-rsa ABCDEFGHIJKLMNOPQR\r\n" \
+ "STUVWXYZ1234567890\r" \
+ "XXYYZZ user@computer\n\n"
+ api.keypair_import(IsA(http.HttpRequest), key1_name,
+ public_key.replace("\r", "")
+ .replace("\n", ""))
+ self.mox.ReplayAll()
+
+ formData = {'method': 'ImportKeypair',
+ 'name': key1_name,
+ 'public_key': public_key}
+ url = reverse('horizon:project:access_and_security:keypairs:import')
+ res = self.client.post(url, formData)
+ self.assertMessageCount(res, success=1)
+
+ def test_import_keypair_invalid_key(self):
+ key_name = "new key pair"
+ public_key = "ABCDEF"
+
+ self.mox.StubOutWithMock(api, 'keypair_import')
+ api.keypair_import(IsA(http.HttpRequest), key_name, public_key) \
+ .AndRaise(self.exceptions.nova)
+ self.mox.ReplayAll()
+
+ formData = {'method': 'ImportKeypair',
+ 'name': key_name,
+ 'public_key': public_key}
+ url = reverse('horizon:project:access_and_security:keypairs:import')
+ res = self.client.post(url, formData, follow=True)
+ self.assertEqual(res.redirect_chain, [])
+ msg = 'Unable to import keypair.'
+ self.assertFormErrors(res, count=1, message=msg)
+
+ def test_generate_keypair_exception(self):
+ keypair = self.keypairs.first()
+
+ self.mox.StubOutWithMock(api, 'keypair_create')
+ api.keypair_create(IsA(http.HttpRequest), keypair.name) \
+ .AndRaise(self.exceptions.nova)
+ self.mox.ReplayAll()
+
+ context = {'keypair_name': keypair.name}
+ url = reverse('horizon:project:access_and_security:keypairs:generate',
+ kwargs={'keypair_name': keypair.name})
+ res = self.client.get(url, context)
+
+ self.assertRedirectsNoFollow(
+ res, reverse('horizon:project:access_and_security:index'))
diff --git a/openstack_dashboard/dashboards/project/access_and_security/keypairs/urls.py b/openstack_dashboard/dashboards/project/access_and_security/keypairs/urls.py
new file mode 100644
index 000000000..50886b205
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/keypairs/urls.py
@@ -0,0 +1,33 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import patterns, url
+
+from .views import CreateView, ImportView, DownloadView, GenerateView
+
+
+urlpatterns = patterns('',
+ url(r'^create/$', CreateView.as_view(), name='create'),
+ url(r'^import/$', ImportView.as_view(), name='import'),
+ url(r'^(?P<keypair_name>[^/]+)/download/$', DownloadView.as_view(),
+ name='download'),
+ url(r'^(?P<keypair_name>[^/]+)/generate/$', GenerateView.as_view(),
+ name='generate'),
+)
diff --git a/openstack_dashboard/dashboards/project/access_and_security/keypairs/views.py b/openstack_dashboard/dashboards/project/access_and_security/keypairs/views.py
new file mode 100644
index 000000000..c27dfdfc1
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/keypairs/views.py
@@ -0,0 +1,82 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.
+
+"""
+Views for managing keypairs.
+"""
+import logging
+
+from django import http
+from django.core.urlresolvers import reverse, reverse_lazy
+from django.template.defaultfilters import slugify
+from django.views.generic import View, TemplateView
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import forms
+from horizon import exceptions
+
+from openstack_dashboard import api
+from .forms import CreateKeypair, ImportKeypair
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateView(forms.ModalFormView):
+ form_class = CreateKeypair
+ template_name = 'project/access_and_security/keypairs/create.html'
+ success_url = 'horizon:project:access_and_security:keypairs:download'
+
+ def get_success_url(self):
+ return reverse(self.success_url,
+ kwargs={"keypair_name": self.request.POST['name']})
+
+
+class ImportView(forms.ModalFormView):
+ form_class = ImportKeypair
+ template_name = 'project/access_and_security/keypairs/import.html'
+ success_url = reverse_lazy('horizon:project:access_and_security:index')
+
+ def get_object_id(self, keypair):
+ return keypair.name
+
+
+class DownloadView(TemplateView):
+ def get_context_data(self, keypair_name=None):
+ return {'keypair_name': keypair_name}
+ template_name = 'project/access_and_security/keypairs/download.html'
+
+
+class GenerateView(View):
+ def get(self, request, keypair_name=None):
+ try:
+ keypair = api.keypair_create(request, keypair_name)
+ except:
+ redirect = reverse('horizon:project:access_and_security:index')
+ exceptions.handle(self.request,
+ _('Unable to create keypair: %(exc)s'),
+ redirect=redirect)
+
+ response = http.HttpResponse(mimetype='application/binary')
+ response['Content-Disposition'] = \
+ 'attachment; filename=%s.pem' % slugify(keypair.name)
+ response.write(keypair.private_key)
+ response['Content-Length'] = str(len(response.content))
+ return response
diff --git a/openstack_dashboard/dashboards/project/access_and_security/panel.py b/openstack_dashboard/dashboards/project/access_and_security/panel.py
new file mode 100644
index 000000000..408316299
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/panel.py
@@ -0,0 +1,30 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+# Copyright 2012 OpenStack LLC
+#
+# 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 AccessAndSecurity(horizon.Panel):
+ name = _("Access & Security")
+ slug = 'access_and_security'
+
+
+dashboard.Project.register(AccessAndSecurity)
diff --git a/openstack_dashboard/dashboards/project/access_and_security/security_groups/__init__.py b/openstack_dashboard/dashboards/project/access_and_security/security_groups/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/security_groups/__init__.py
diff --git a/openstack_dashboard/dashboards/project/access_and_security/security_groups/forms.py b/openstack_dashboard/dashboards/project/access_and_security/security_groups/forms.py
new file mode 100644
index 000000000..359016d41
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/security_groups/forms.py
@@ -0,0 +1,174 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 validators
+from django.core.urlresolvers import reverse
+from django.forms import ValidationError
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import messages
+from horizon.utils.validators import validate_port_range
+from horizon.utils import fields
+
+from openstack_dashboard import api
+
+
+class CreateGroup(forms.SelfHandlingForm):
+ name = forms.CharField(label=_("Name"),
+ validators=[validators.validate_slug])
+ description = forms.CharField(label=_("Description"))
+
+ def handle(self, request, data):
+ try:
+ sg = api.security_group_create(request,
+ data['name'],
+ data['description'])
+ messages.success(request,
+ _('Successfully created security group: %s')
+ % data['name'])
+ return sg
+ except:
+ redirect = reverse("horizon:project:access_and_security:index")
+ exceptions.handle(request,
+ _('Unable to create security group.'),
+ redirect=redirect)
+
+
+class AddRule(forms.SelfHandlingForm):
+ ip_protocol = forms.ChoiceField(label=_('IP Protocol'),
+ choices=[('tcp', 'TCP'),
+ ('udp', 'UDP'),
+ ('icmp', 'ICMP')],
+ help_text=_("The protocol which this "
+ "rule should be applied to."),
+ widget=forms.Select(attrs={'class':
+ 'switchable'}))
+ from_port = forms.IntegerField(label=_("From Port"),
+ help_text=_("TCP/UDP: Enter integer value "
+ "between 1 and 65535. ICMP: "
+ "enter a value for ICMP type "
+ "in the range (-1: 255)"),
+ widget=forms.TextInput(
+ attrs={'data': _('From Port'),
+ 'data-icmp': _('Type')}),
+ validators=[validate_port_range])
+ to_port = forms.IntegerField(label=_("To Port"),
+ help_text=_("TCP/UDP: Enter integer value "
+ "between 1 and 65535. ICMP: "
+ "enter a value for ICMP code "
+ "in the range (-1: 255)"),
+ widget=forms.TextInput(
+ attrs={'data': _('To Port'),
+ 'data-icmp': _('Code')}),
+ validators=[validate_port_range])
+
+ source_group = forms.ChoiceField(label=_('Source Group'),
+ required=False,
+ help_text=_("To specify an allowed IP "
+ "range, select CIDR. To "
+ "allow access from all "
+ "members of another security "
+ "group select Source Group."))
+ cidr = fields.IPField(label=_("CIDR"),
+ required=False,
+ initial="0.0.0.0/0",
+ help_text=_("Classless Inter-Domain Routing "
+ "(e.g. 192.168.0.0/24)"),
+ version=fields.IPv4 | fields.IPv6,
+ mask=True)
+
+ security_group_id = forms.IntegerField(widget=forms.HiddenInput())
+
+ def __init__(self, *args, **kwargs):
+ sg_list = kwargs.pop('sg_list', [])
+ super(AddRule, self).__init__(*args, **kwargs)
+ # Determine if there are security groups available for the
+ # source group option; add the choices and enable the option if so.
+ security_groups_choices = [("", "CIDR")]
+ if sg_list:
+ security_groups_choices.append(('Security Group', sg_list))
+ self.fields['source_group'].choices = security_groups_choices
+
+ def clean(self):
+ cleaned_data = super(AddRule, self).clean()
+ from_port = cleaned_data.get("from_port", None)
+ to_port = cleaned_data.get("to_port", None)
+ cidr = cleaned_data.get("cidr", None)
+ ip_proto = cleaned_data.get('ip_protocol', None)
+ source_group = cleaned_data.get("source_group", None)
+
+ if ip_proto == 'icmp':
+ if from_port is None:
+ msg = _('The ICMP type is invalid.')
+ raise ValidationError(msg)
+ if to_port is None:
+ msg = _('The ICMP code is invalid.')
+ raise ValidationError(msg)
+ if from_port not in xrange(-1, 256):
+ msg = _('The ICMP type not in range (-1, 255)')
+ raise ValidationError(msg)
+ if to_port not in xrange(-1, 256):
+ msg = _('The ICMP code not in range (-1, 255)')
+ raise ValidationError(msg)
+ else:
+ if from_port is None:
+ msg = _('The "from" port number is invalid.')
+ raise ValidationError(msg)
+ if to_port is None:
+ msg = _('The "to" port number is invalid.')
+ raise ValidationError(msg)
+ if to_port < from_port:
+ msg = _('The "to" port number must be greater than '
+ 'or equal to the "from" port number.')
+ raise ValidationError(msg)
+
+ if source_group and cidr != self.fields['cidr'].initial:
+ # Specifying a source group *and* a custom CIDR is invalid.
+ msg = _('Either CIDR or Source Group may be specified, '
+ 'but not both.')
+ raise ValidationError(msg)
+ elif source_group:
+ # If a source group is specified, clear the CIDR from its default
+ cleaned_data['cidr'] = None
+ else:
+ # If only cidr is specified, clear the source_group entirely
+ cleaned_data['source_group'] = None
+
+ return cleaned_data
+
+ def handle(self, request, data):
+ try:
+ rule = api.security_group_rule_create(request,
+ data['security_group_id'],
+ data['ip_protocol'],
+ data['from_port'],
+ data['to_port'],
+ data['cidr'],
+ data['source_group'])
+ messages.success(request,
+ _('Successfully added rule: %s') % unicode(rule))
+ return rule
+ except:
+ redirect = reverse("horizon:project:access_and_security:index")
+ exceptions.handle(request,
+ _('Unable to add rule to security group.'),
+ redirect=redirect)
diff --git a/openstack_dashboard/dashboards/project/access_and_security/security_groups/tables.py b/openstack_dashboard/dashboards/project/access_and_security/security_groups/tables.py
new file mode 100644
index 000000000..b669ed931
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/security_groups/tables.py
@@ -0,0 +1,109 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import tables
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class DeleteGroup(tables.DeleteAction):
+ data_type_singular = _("Security Group")
+ data_type_plural = _("Security Groups")
+
+ def allowed(self, request, security_group=None):
+ if not security_group:
+ return True
+ return security_group.name != 'default'
+
+ def delete(self, request, obj_id):
+ api.security_group_delete(request, obj_id)
+
+
+class CreateGroup(tables.LinkAction):
+ name = "create"
+ verbose_name = _("Create Security Group")
+ url = "horizon:project:access_and_security:security_groups:create"
+ classes = ("ajax-modal", "btn-create")
+
+
+class EditRules(tables.LinkAction):
+ name = "edit_rules"
+ verbose_name = _("Edit Rules")
+ url = "horizon:project:access_and_security:security_groups:edit_rules"
+ classes = ("ajax-modal", "btn-edit")
+
+
+class SecurityGroupsTable(tables.DataTable):
+ name = tables.Column("name", verbose_name=_("Name"))
+ description = tables.Column("description", verbose_name=_("Description"))
+
+ def sanitize_id(self, obj_id):
+ return int(obj_id)
+
+ class Meta:
+ name = "security_groups"
+ verbose_name = _("Security Groups")
+ table_actions = (CreateGroup, DeleteGroup)
+ row_actions = (EditRules, DeleteGroup)
+
+
+class DeleteRule(tables.DeleteAction):
+ data_type_singular = _("Rule")
+ data_type_plural = _("Rules")
+
+ def delete(self, request, obj_id):
+ api.security_group_rule_delete(request, obj_id)
+
+ def get_success_url(self, request):
+ return reverse("horizon:project:access_and_security:index")
+
+
+def get_source(rule):
+ if 'cidr' in rule.ip_range:
+ return rule.ip_range['cidr'] + ' (CIDR)'
+ elif 'name' in rule.group:
+ return rule.group['name']
+ else:
+ return None
+
+
+class RulesTable(tables.DataTable):
+ protocol = tables.Column("ip_protocol",
+ verbose_name=_("IP Protocol"),
+ filters=(unicode.upper,))
+ from_port = tables.Column("from_port", verbose_name=_("From Port"))
+ to_port = tables.Column("to_port", verbose_name=_("To Port"))
+ source = tables.Column(get_source, verbose_name=_("Source"))
+
+ def sanitize_id(self, obj_id):
+ return int(obj_id)
+
+ def get_object_display(self, rule):
+ return unicode(rule)
+
+ class Meta:
+ name = "rules"
+ verbose_name = _("Security Group Rules")
+ table_actions = (DeleteRule,)
+ row_actions = (DeleteRule,)
diff --git a/openstack_dashboard/dashboards/project/access_and_security/security_groups/tests.py b/openstack_dashboard/dashboards/project/access_and_security/security_groups/tests.py
new file mode 100644
index 000000000..f38b947a0
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/security_groups/tests.py
@@ -0,0 +1,375 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 import http
+from django.conf import settings
+from django.core.urlresolvers import reverse
+
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+from .tables import SecurityGroupsTable, RulesTable
+
+
+INDEX_URL = reverse('horizon:project:access_and_security:index')
+SG_CREATE_URL = reverse('horizon:project:access_and_security:'
+ 'security_groups:create')
+
+
+def strip_absolute_base(uri):
+ return uri.split(settings.TESTSERVER, 1)[-1]
+
+
+class SecurityGroupsViewTests(test.TestCase):
+ def setUp(self):
+ super(SecurityGroupsViewTests, self).setUp()
+ sec_group = self.security_groups.first()
+ self.edit_url = reverse('horizon:project:access_and_security:'
+ 'security_groups:edit_rules',
+ args=[sec_group.id])
+
+ def test_create_security_groups_get(self):
+ res = self.client.get(SG_CREATE_URL)
+ self.assertTemplateUsed(res,
+ 'project/access_and_security/security_groups/create.html')
+
+ def test_create_security_groups_post(self):
+ sec_group = self.security_groups.first()
+ self.mox.StubOutWithMock(api, 'security_group_create')
+ api.security_group_create(IsA(http.HttpRequest),
+ sec_group.name,
+ sec_group.description).AndReturn(sec_group)
+ self.mox.ReplayAll()
+
+ formData = {'method': 'CreateGroup',
+ 'name': sec_group.name,
+ 'description': sec_group.description}
+ res = self.client.post(SG_CREATE_URL, formData)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ def test_create_security_groups_post_exception(self):
+ sec_group = self.security_groups.first()
+ self.mox.StubOutWithMock(api, 'security_group_create')
+ api.security_group_create(IsA(http.HttpRequest),
+ sec_group.name,
+ sec_group.description) \
+ .AndRaise(self.exceptions.nova)
+ self.mox.ReplayAll()
+
+ formData = {'method': 'CreateGroup',
+ 'name': sec_group.name,
+ 'description': sec_group.description}
+ res = self.client.post(SG_CREATE_URL, formData)
+ self.assertMessageCount(error=1)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ def test_edit_rules_get(self):
+ sec_group = self.security_groups.first()
+ sec_group_list = self.security_groups.list()
+
+ self.mox.StubOutWithMock(api, 'security_group_get')
+ api.security_group_get(IsA(http.HttpRequest),
+ sec_group.id).AndReturn(sec_group)
+ self.mox.StubOutWithMock(api, 'security_group_list')
+ api.security_group_list(
+ IsA(http.HttpRequest)).AndReturn(sec_group_list)
+ self.mox.ReplayAll()
+
+ res = self.client.get(self.edit_url)
+ self.assertTemplateUsed(res,
+ 'project/access_and_security/security_groups/edit_rules.html')
+ self.assertItemsEqual(res.context['security_group'].name,
+ sec_group.name)
+
+ def test_edit_rules_get_exception(self):
+ sec_group = self.security_groups.first()
+
+ self.mox.StubOutWithMock(api, 'security_group_get')
+ self.mox.StubOutWithMock(api, 'security_group_list')
+
+ api.security_group_get(IsA(http.HttpRequest),
+ sec_group.id).AndRaise(self.exceptions.nova)
+ self.mox.ReplayAll()
+
+ res = self.client.get(self.edit_url)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ def test_edit_rules_add_rule_cidr(self):
+ sec_group = self.security_groups.first()
+ sec_group_list = self.security_groups.list()
+ rule = self.security_group_rules.first()
+
+ self.mox.StubOutWithMock(api, 'security_group_rule_create')
+ self.mox.StubOutWithMock(api, 'security_group_list')
+ api.security_group_rule_create(IsA(http.HttpRequest),
+ sec_group.id,
+ rule.ip_protocol,
+ int(rule.from_port),
+ int(rule.to_port),
+ rule.ip_range['cidr'],
+ None).AndReturn(rule)
+ api.security_group_list(
+ IsA(http.HttpRequest)).AndReturn(sec_group_list)
+ self.mox.ReplayAll()
+
+ formData = {'method': 'AddRule',
+ 'security_group_id': sec_group.id,
+ 'from_port': rule.from_port,
+ 'to_port': rule.to_port,
+ 'ip_protocol': rule.ip_protocol,
+ 'cidr': rule.ip_range['cidr'],
+ 'source_group': ''}
+ res = self.client.post(self.edit_url, formData)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ def test_edit_rules_add_rule_cidr_and_source_group(self):
+ sec_group = self.security_groups.first()
+ sec_group_other = self.security_groups.get(id=2)
+ sec_group_list = self.security_groups.list()
+ rule = self.security_group_rules.first()
+
+ self.mox.StubOutWithMock(api, 'security_group_get')
+ self.mox.StubOutWithMock(api, 'security_group_list')
+ api.security_group_get(IsA(http.HttpRequest),
+ sec_group.id).AndReturn(sec_group)
+ api.security_group_list(
+ IsA(http.HttpRequest)).AndReturn(sec_group_list)
+ self.mox.ReplayAll()
+
+ formData = {'method': 'AddRule',
+ 'security_group_id': sec_group.id,
+ 'from_port': rule.from_port,
+ 'to_port': rule.to_port,
+ 'ip_protocol': rule.ip_protocol,
+ 'cidr': "127.0.0.1/32",
+ 'source_group': sec_group_other.id}
+ res = self.client.post(self.edit_url, formData)
+ self.assertNoMessages()
+ msg = 'Either CIDR or Source Group may be specified, but not both.'
+ self.assertFormErrors(res, count=1, message=msg)
+
+ def test_edit_rules_add_rule_self_as_source_group(self):
+ sec_group = self.security_groups.first()
+ sec_group_list = self.security_groups.list()
+ rule = self.security_group_rules.get(id=3)
+
+ self.mox.StubOutWithMock(api, 'security_group_rule_create')
+ self.mox.StubOutWithMock(api, 'security_group_list')
+ api.security_group_rule_create(IsA(http.HttpRequest),
+ sec_group.id,
+ rule.ip_protocol,
+ int(rule.from_port),
+ int(rule.to_port),
+ None,
+ u'%s' % sec_group.id).AndReturn(rule)
+ api.security_group_list(
+ IsA(http.HttpRequest)).AndReturn(sec_group_list)
+ self.mox.ReplayAll()
+
+ formData = {'method': 'AddRule',
+ 'security_group_id': sec_group.id,
+ 'from_port': rule.from_port,
+ 'to_port': rule.to_port,
+ 'ip_protocol': rule.ip_protocol,
+ 'cidr': '0.0.0.0/0',
+ 'source_group': sec_group.id}
+ res = self.client.post(self.edit_url, formData)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ def test_edit_rules_invalid_port_range(self):
+ sec_group = self.security_groups.first()
+ sec_group_list = self.security_groups.list()
+ rule = self.security_group_rules.first()
+
+ self.mox.StubOutWithMock(api, 'security_group_get')
+ api.security_group_get(IsA(http.HttpRequest),
+ sec_group.id).AndReturn(sec_group)
+ self.mox.StubOutWithMock(api, 'security_group_list')
+ api.security_group_list(
+ IsA(http.HttpRequest)).AndReturn(sec_group_list)
+ self.mox.ReplayAll()
+
+ formData = {'method': 'AddRule',
+ 'security_group_id': sec_group.id,
+ 'from_port': rule.from_port,
+ 'to_port': int(rule.from_port) - 1,
+ 'ip_protocol': rule.ip_protocol,
+ 'cidr': rule.ip_range['cidr'],
+ 'source_group': ''}
+ res = self.client.post(self.edit_url, formData)
+ self.assertNoMessages()
+ self.assertContains(res, "greater than or equal to")
+
+ @test.create_stubs({api: ('security_group_get', 'security_group_list')})
+ def test_edit_rules_invalid_icmp_rule(self):
+ sec_group = self.security_groups.first()
+ sec_group_list = self.security_groups.list()
+ icmp_rule = self.security_group_rules.list()[1]
+
+ api.security_group_get(IsA(http.HttpRequest),
+ sec_group.id).AndReturn(sec_group)
+ api.security_group_list(
+ IsA(http.HttpRequest)).AndReturn(sec_group_list)
+ api.security_group_get(IsA(http.HttpRequest),
+ sec_group.id).AndReturn(sec_group)
+ api.security_group_list(
+ IsA(http.HttpRequest)).AndReturn(sec_group_list)
+ api.security_group_get(IsA(http.HttpRequest),
+ sec_group.id).AndReturn(sec_group)
+ api.security_group_list(
+ IsA(http.HttpRequest)).AndReturn(sec_group_list)
+ api.security_group_get(IsA(http.HttpRequest),
+ sec_group.id).AndReturn(sec_group)
+ api.security_group_list(
+ IsA(http.HttpRequest)).AndReturn(sec_group_list)
+ self.mox.ReplayAll()
+
+ formData = {'method': 'AddRule',
+ 'security_group_id': sec_group.id,
+ 'from_port': 256,
+ 'to_port': icmp_rule.to_port,
+ 'ip_protocol': icmp_rule.ip_protocol,
+ 'cidr': icmp_rule.ip_range['cidr'],
+ 'source_group': ''}
+ res = self.client.post(self.edit_url, formData)
+ self.assertNoMessages()
+ self.assertContains(res, "The ICMP type not in range (-1, 255)")
+
+ formData = {'method': 'AddRule',
+ 'security_group_id': sec_group.id,
+ 'from_port': icmp_rule.from_port,
+ 'to_port': 256,
+ 'ip_protocol': icmp_rule.ip_protocol,
+ 'cidr': icmp_rule.ip_range['cidr'],
+ 'source_group': ''}
+ res = self.client.post(self.edit_url, formData)
+ self.assertNoMessages()
+ self.assertContains(res, "The ICMP code not in range (-1, 255)")
+
+ formData = {'method': 'AddRule',
+ 'security_group_id': sec_group.id,
+ 'from_port': icmp_rule.from_port,
+ 'to_port': None,
+ 'ip_protocol': icmp_rule.ip_protocol,
+ 'cidr': icmp_rule.ip_range['cidr'],
+ 'source_group': ''}
+ res = self.client.post(self.edit_url, formData)
+ self.assertNoMessages()
+ self.assertContains(res, "The ICMP code is invalid")
+
+ formData = {'method': 'AddRule',
+ 'security_group_id': sec_group.id,
+ 'from_port': None,
+ 'to_port': icmp_rule.to_port,
+ 'ip_protocol': icmp_rule.ip_protocol,
+ 'cidr': icmp_rule.ip_range['cidr'],
+ 'source_group': ''}
+ res = self.client.post(self.edit_url, formData)
+ self.assertNoMessages()
+ self.assertContains(res, "The ICMP type is invalid")
+
+ def test_edit_rules_add_rule_exception(self):
+ sec_group = self.security_groups.first()
+ sec_group_list = self.security_groups.list()
+ rule = self.security_group_rules.first()
+
+ self.mox.StubOutWithMock(api, 'security_group_rule_create')
+ self.mox.StubOutWithMock(api, 'security_group_list')
+ api.security_group_rule_create(IsA(http.HttpRequest),
+ sec_group.id,
+ rule.ip_protocol,
+ int(rule.from_port),
+ int(rule.to_port),
+ rule.ip_range['cidr'],
+ None).AndRaise(self.exceptions.nova)
+ api.security_group_list(
+ IsA(http.HttpRequest)).AndReturn(sec_group_list)
+ self.mox.ReplayAll()
+
+ formData = {'method': 'AddRule',
+ 'security_group_id': sec_group.id,
+ 'from_port': rule.from_port,
+ 'to_port': rule.to_port,
+ 'ip_protocol': rule.ip_protocol,
+ 'cidr': rule.ip_range['cidr'],
+ 'source_group': ''}
+ res = self.client.post(self.edit_url, formData)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ def test_edit_rules_delete_rule(self):
+ sec_group = self.security_groups.first()
+ rule = self.security_group_rules.first()
+
+ self.mox.StubOutWithMock(api, 'security_group_rule_delete')
+ api.security_group_rule_delete(IsA(http.HttpRequest), rule.id)
+ self.mox.ReplayAll()
+
+ form_data = {"action": "rules__delete__%s" % rule.id}
+ req = self.factory.post(self.edit_url, form_data)
+ table = RulesTable(req, sec_group.rules)
+ handled = table.maybe_handle()
+ self.assertEqual(strip_absolute_base(handled['location']), INDEX_URL)
+
+ def test_edit_rules_delete_rule_exception(self):
+ rule = self.security_group_rules.first()
+
+ self.mox.StubOutWithMock(api, 'security_group_rule_delete')
+ api.security_group_rule_delete(IsA(http.HttpRequest),
+ rule.id).AndRaise(self.exceptions.nova)
+ self.mox.ReplayAll()
+
+ form_data = {"action": "rules__delete__%s" % rule.id}
+ req = self.factory.post(self.edit_url, form_data)
+ table = RulesTable(req, self.security_group_rules.list())
+ handled = table.maybe_handle()
+ self.assertEqual(strip_absolute_base(handled['location']),
+ INDEX_URL)
+
+ def test_delete_group(self):
+ sec_group = self.security_groups.get(name="other_group")
+
+ self.mox.StubOutWithMock(api, 'security_group_delete')
+ api.security_group_delete(IsA(http.HttpRequest), sec_group.id)
+ self.mox.ReplayAll()
+
+ form_data = {"action": "security_groups__delete__%s" % sec_group.id}
+ req = self.factory.post(INDEX_URL, form_data)
+ table = SecurityGroupsTable(req, self.security_groups.list())
+ handled = table.maybe_handle()
+ self.assertEqual(strip_absolute_base(handled['location']),
+ INDEX_URL)
+
+ def test_delete_group_exception(self):
+ sec_group = self.security_groups.get(name="other_group")
+
+ self.mox.StubOutWithMock(api, 'security_group_delete')
+ api.security_group_delete(IsA(http.HttpRequest),
+ sec_group.id).AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ form_data = {"action": "security_groups__delete__%s" % sec_group.id}
+ req = self.factory.post(INDEX_URL, form_data)
+ table = SecurityGroupsTable(req, self.security_groups.list())
+ handled = table.maybe_handle()
+
+ self.assertEqual(strip_absolute_base(handled['location']),
+ INDEX_URL)
diff --git a/openstack_dashboard/dashboards/project/access_and_security/security_groups/urls.py b/openstack_dashboard/dashboards/project/access_and_security/security_groups/urls.py
new file mode 100644
index 000000000..c4dbf582e
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/security_groups/urls.py
@@ -0,0 +1,30 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import patterns, url
+
+from .views import CreateView, EditRulesView
+
+
+urlpatterns = patterns('',
+ url(r'^create/$', CreateView.as_view(), name='create'),
+ url(r'^(?P<security_group_id>[^/]+)/edit_rules/$',
+ EditRulesView.as_view(),
+ name='edit_rules'))
diff --git a/openstack_dashboard/dashboards/project/access_and_security/security_groups/views.py b/openstack_dashboard/dashboards/project/access_and_security/security_groups/views.py
new file mode 100644
index 000000000..67d0c953f
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/security_groups/views.py
@@ -0,0 +1,121 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.
+
+"""
+Views for managing instances.
+"""
+import logging
+
+from django import shortcuts
+from django.core.urlresolvers import reverse_lazy
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import tables
+
+from openstack_dashboard import api
+from .forms import CreateGroup, AddRule
+from .tables import RulesTable
+
+
+LOG = logging.getLogger(__name__)
+
+
+class EditRulesView(tables.DataTableView, forms.ModalFormView):
+ table_class = RulesTable
+ form_class = AddRule
+ template_name = ('project/access_and_security/security_groups/'
+ 'edit_rules.html')
+ success_url = reverse_lazy("horizon:project:access_and_security:index")
+
+ def get_data(self):
+ security_group_id = int(self.kwargs['security_group_id'])
+ try:
+ self.object = api.security_group_get(self.request,
+ security_group_id)
+ rules = [api.nova.SecurityGroupRule(rule) for
+ rule in self.object.rules]
+ except:
+ self.object = None
+ rules = []
+ exceptions.handle(self.request,
+ _('Unable to retrieve security group.'))
+ return rules
+
+ def get_initial(self):
+ return {'security_group_id': self.kwargs['security_group_id']}
+
+ def get_form_kwargs(self):
+ kwargs = super(EditRulesView, self).get_form_kwargs()
+
+ try:
+ groups = api.security_group_list(self.request)
+ except:
+ groups = []
+ exceptions.handle(self.request,
+ _("Unable to retrieve security groups."))
+
+ security_groups = []
+ for group in groups:
+ if group.id == int(self.kwargs['security_group_id']):
+ security_groups.append((group.id,
+ _("%s (current)") % group.name))
+ else:
+ security_groups.append((group.id, group.name))
+ kwargs['sg_list'] = security_groups
+ return kwargs
+
+ def get_form(self):
+ if not hasattr(self, "_form"):
+ form_class = self.get_form_class()
+ self._form = super(EditRulesView, self).get_form(form_class)
+ return self._form
+
+ def get_context_data(self, **kwargs):
+ context = super(EditRulesView, self).get_context_data(**kwargs)
+ context['form'] = self.get_form()
+ if self.request.is_ajax():
+ context['hide'] = True
+ return context
+
+ def get(self, request, *args, **kwargs):
+ # Table action handling
+ handled = self.construct_tables()
+ if handled:
+ return handled
+ if not self.object: # Set during table construction.
+ return shortcuts.redirect(self.success_url)
+ context = self.get_context_data(**kwargs)
+ context['security_group'] = self.object
+ return self.render_to_response(context)
+
+ def post(self, request, *args, **kwargs):
+ form = self.get_form()
+ if form.is_valid():
+ return self.form_valid(form)
+ else:
+ return self.get(request, *args, **kwargs)
+
+
+class CreateView(forms.ModalFormView):
+ form_class = CreateGroup
+ template_name = 'project/access_and_security/security_groups/create.html'
+ success_url = reverse_lazy('horizon:project:access_and_security:index')
diff --git a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html
new file mode 100644
index 000000000..abc7e18df
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html
@@ -0,0 +1,33 @@
+{% extends "horizon/common/_modal_form.html" %}
+
+{% load horizon i18n %}
+
+{% block form_id %}associate_floating_ip_form{% endblock %}
+{% block form_action %}{% url horizon:project:access_and_security:floating_ips:allocate %}{% endblock %}
+
+{% block modal-header %}{% trans "Allocate Floating IP" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description:" %}</h3>
+ <p>{% trans "Allocate a floating IP from a given floating ip pool." %}</p>
+
+ <h3>{% trans "Project Quotas" %}</h3>
+ <div class="quota_title">
+ <strong>{% trans "Floating IP" %} <span>({{ usages.floating_ips.used }})</span></strong>
+ <p>{{ usages.floating_ips.available|quota }}</p>
+ </div>
+ <div class="clearfix"></div>
+ <div class="quota_bar">{% horizon_progress_bar usages.floating_ips.used usages.floating_ips.quota %}</div>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right {% ifequal usages.floating_ips.used usages.floating_ips.quota %}disabled" type="button"{% else %}" type="submit"{% endifequal %} value="{% trans "Allocate IP" %}" />
+ <a href="{% url horizon:project:access_and_security:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html
new file mode 100644
index 000000000..8679b9e8f
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html
@@ -0,0 +1,7 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Allocate Floating IP" %}{% endblock %}
+
+{% block main %}
+ {% include 'project/access_and_security/floating_ips/_allocate.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html
new file mode 100644
index 000000000..21ba418d1
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Associate Floating IP" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Associate Floating IP") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'horizon/common/_workflow.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/index.html b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/index.html
new file mode 100644
index 000000000..5284b87f1
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/index.html
@@ -0,0 +1,21 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Access &amp; Security{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Access &amp; Security") %}
+{% endblock page_header %}
+
+{% block main %}
+ <div id="floating_ips">
+ {{ floating_ips_table.render }}
+ </div>
+
+ <div id="security_groups">
+ {{ security_groups_table.render }}
+ </div>
+
+ <div id="keypairs">
+ {{ keypairs_table.render }}
+ </div>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html
new file mode 100644
index 000000000..db9ee8d39
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}create_keypair_form{% endblock %}
+{% block form_action %}{% url horizon:project:access_and_security:keypairs:create %}{% endblock %}
+
+{% block modal-header %}{% trans "Create Keypair" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "Keypairs are ssh credentials which are injected into images when they are launched. Creating a new key pair registers the public key and downloads the private key (a .pem file)." %}</p>
+ <p>{% trans "Protect and use the key as you would any normal ssh private key." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Keypair" %}" />
+ <a href="{% url horizon:project:access_and_security:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html
new file mode 100644
index 000000000..2eca705b7
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}import_keypair_form{% endblock %}
+{% block form_action %}{% url horizon:project:access_and_security:keypairs:import %}{% endblock %}
+
+{% block modal-header %}{% trans "Import Keypair" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "Keypairs are ssh credentials which are injected into images when they are launched. Creating a new key pair registers the public key and downloads the private key (a .pem file)." %}</p>
+ <p>{% trans "Protect and use the key as you would any normal ssh private key." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Import Keypair" %}" />
+ <a href="{% url horizon:project:access_and_security:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html
new file mode 100644
index 000000000..4f98bb1f1
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html
@@ -0,0 +1,12 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Create Keypair{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Create Keypair") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'project/access_and_security/keypairs/_create.html' %}
+{% endblock %}
+
diff --git a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html
new file mode 100644
index 000000000..3cc9de587
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html
@@ -0,0 +1,21 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% blocktrans %}Download Keypair{% endblocktrans %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Download Keypair") %}
+{% endblock page_header %}
+
+{% block main %}
+ <div class="modal-header">
+ <h3>{% blocktrans %}The keypair &quot;{{ keypair_name }}&quot; should download automatically. If not use the link below.{% endblocktrans %}</h3>
+ </div>
+ <div class="modal-body clearfix">
+ <a href="{% url horizon:project:access_and_security:keypairs:generate keypair_name %}">
+ {% blocktrans %}Download keypair &quot;{{ keypair_name}}&quot;{% endblocktrans %}
+ </a>
+ </div>
+ <script type="text/javascript" charset="utf-8">
+ document.location = '{% url horizon:project:access_and_security:keypairs:generate keypair_name %}';
+ </script>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html
new file mode 100644
index 000000000..7a9199bfc
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html
@@ -0,0 +1,12 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Import Keypair{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Import Keypair") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'project/access_and_security/keypairs/_import.html' %}
+{% endblock %}
+
diff --git a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html
new file mode 100644
index 000000000..2c8eed7e1
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}create_security_group_form{% endblock %}
+{% block form_action %}{% url horizon:project:access_and_security:security_groups:create %}{% endblock %}
+
+{% block modal-header %}{% trans "Create Security Group" %}{% endblock %}
+{% block modal_id %}create_security_group_modal{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "From here you can create a new security group" %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Security Group" %}" />
+ <a href="{% url horizon:project:access_and_security:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html
new file mode 100644
index 000000000..fa51e74f0
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html
@@ -0,0 +1,21 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}security_group_rule_form{% endblock %}
+{% block form_action %}{% url horizon:project:access_and_security:security_groups:edit_rules security_group.id %}{% endblock %}
+{% block form_class %}{{ block.super }} horizontal split_five{% endblock %}
+
+{% block modal_id %}security_group_rule_modal{% endblock %}
+{% block modal-header %}{% trans "Edit Security Group Rules" %}{% endblock %}
+
+{% block modal-body %}
+ <h3>{% trans "Add Rule" %}</h3>
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Add Rule" %}" />
+ <a href="{% url horizon:project:access_and_security:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html
new file mode 100644
index 000000000..cd102ab47
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Create Security Group{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Create Security Group") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'project/access_and_security/security_groups/_create.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html
new file mode 100644
index 000000000..4afe3f704
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Edit Security Group Rules{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Edit Security Group Rules") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include "project/access_and_security/security_groups/_edit_rules.html" %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/access_and_security/tests.py b/openstack_dashboard/dashboards/project/access_and_security/tests.py
new file mode 100644
index 000000000..180c9904c
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/tests.py
@@ -0,0 +1,88 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 copy import deepcopy
+
+from django import http
+from django.core.urlresolvers import reverse
+
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+class AccessAndSecurityTests(test.TestCase):
+ def test_index(self):
+ keypairs = self.keypairs.list()
+ sec_groups = self.security_groups.list()
+ floating_ips = self.floating_ips.list()
+ self.mox.StubOutWithMock(api, 'tenant_floating_ip_list')
+ self.mox.StubOutWithMock(api, 'security_group_list')
+ self.mox.StubOutWithMock(api.nova, 'keypair_list')
+ self.mox.StubOutWithMock(api.nova, 'server_list')
+
+ api.nova.server_list(IsA(http.HttpRequest),
+ all_tenants=True).AndReturn(self.servers.list())
+ api.nova.keypair_list(IsA(http.HttpRequest)).AndReturn(keypairs)
+ api.tenant_floating_ip_list(IsA(http.HttpRequest)) \
+ .AndReturn(floating_ips)
+ api.security_group_list(IsA(http.HttpRequest)).AndReturn(sec_groups)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:access_and_security:index')
+ res = self.client.get(url)
+
+ self.assertTemplateUsed(res, 'project/access_and_security/index.html')
+ self.assertItemsEqual(res.context['keypairs_table'].data, keypairs)
+ self.assertItemsEqual(res.context['security_groups_table'].data,
+ sec_groups)
+ self.assertItemsEqual(res.context['floating_ips_table'].data,
+ floating_ips)
+
+ def test_association(self):
+ servers = self.servers.list()
+
+ # Add duplicate instance name to test instance name with [IP]
+ # change id and private IP
+ server3 = api.nova.Server(self.servers.first(), self.request)
+ server3.id = 101
+ server3.addresses = deepcopy(server3.addresses)
+ server3.addresses['private'][0]['addr'] = "10.0.0.5"
+ self.servers.add(server3)
+
+ self.mox.StubOutWithMock(api.nova, 'tenant_floating_ip_list')
+ self.mox.StubOutWithMock(api.nova, 'server_list')
+ api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.floating_ips.list())
+ api.nova.server_list(IsA(http.HttpRequest)).AndReturn(servers)
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse("horizon:project:access_and_security:"
+ "floating_ips:associate"))
+ self.assertTemplateUsed(res,
+ 'project/access_and_security/floating_ips/associate.html')
+
+ self.assertContains(res,
+ '<option value="1">server_1 (1)</option>')
+ self.assertContains(res,
+ '<option value="101">server_1 (101)</option>')
+ self.assertContains(res, '<option value="2">server_2 (2)</option>')
diff --git a/openstack_dashboard/dashboards/project/access_and_security/urls.py b/openstack_dashboard/dashboards/project/access_and_security/urls.py
new file mode 100644
index 000000000..ce94d6ac6
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/urls.py
@@ -0,0 +1,35 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import url, patterns, include
+
+from .floating_ips import urls as fip_urls
+from .keypairs import urls as keypair_urls
+from .security_groups import urls as sec_group_urls
+from .views import IndexView
+
+
+urlpatterns = patterns('',
+ url(r'^$', IndexView.as_view(), name='index'),
+ url(r'keypairs/', include(keypair_urls, namespace='keypairs')),
+ url(r'floating_ips/', include(fip_urls, namespace='floating_ips')),
+ url(r'security_groups/',
+ include(sec_group_urls, namespace='security_groups')),
+)
diff --git a/openstack_dashboard/dashboards/project/access_and_security/views.py b/openstack_dashboard/dashboards/project/access_and_security/views.py
new file mode 100644
index 000000000..4cee611e0
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/access_and_security/views.py
@@ -0,0 +1,84 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+# Copyright 2012 OpenStack LLC
+#
+# 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.
+
+"""
+Views for Instances and Volumes.
+"""
+import logging
+
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tables
+
+from openstack_dashboard import api
+from .keypairs.tables import KeypairsTable
+from .floating_ips.tables import FloatingIPsTable
+from .security_groups.tables import SecurityGroupsTable
+
+
+LOG = logging.getLogger(__name__)
+
+
+class IndexView(tables.MultiTableView):
+ table_classes = (KeypairsTable, SecurityGroupsTable, FloatingIPsTable)
+ template_name = 'project/access_and_security/index.html'
+
+ def get_keypairs_data(self):
+ try:
+ keypairs = api.nova.keypair_list(self.request)
+ except:
+ keypairs = []
+ exceptions.handle(self.request,
+ _('Unable to retrieve keypair list.'))
+ return keypairs
+
+ def get_security_groups_data(self):
+ try:
+ security_groups = api.security_group_list(self.request)
+ except:
+ security_groups = []
+ exceptions.handle(self.request,
+ _('Unable to retrieve security groups.'))
+ return security_groups
+
+ def get_floating_ips_data(self):
+ try:
+ floating_ips = api.tenant_floating_ip_list(self.request)
+ except:
+ floating_ips = []
+ exceptions.handle(self.request,
+ _('Unable to retrieve floating IP addresses.'))
+
+ instances = []
+ try:
+ instances = api.nova.server_list(self.request, all_tenants=True)
+ except:
+ exceptions.handle(self.request,
+ _('Unable to retrieve instance list.'))
+
+ instances_dict = dict([(obj.id, obj) for obj in instances])
+
+ for ip in floating_ips:
+ ip.instance_name = instances_dict[ip.instance_id].name \
+ if ip.instance_id in instances_dict else None
+
+ return floating_ips
diff --git a/openstack_dashboard/dashboards/project/containers/__init__.py b/openstack_dashboard/dashboards/project/containers/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/containers/__init__.py
diff --git a/openstack_dashboard/dashboards/project/containers/browsers.py b/openstack_dashboard/dashboards/project/containers/browsers.py
new file mode 100644
index 000000000..eaf5b9c92
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/containers/browsers.py
@@ -0,0 +1,33 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 _
+
+from horizon import browsers
+
+from .tables import ContainersTable, ObjectsTable
+
+
+class ContainerBrowser(browsers.ResourceBrowser):
+ name = "swift"
+ verbose_name = _("Swift")
+ navigation_table_class = ContainersTable
+ content_table_class = ObjectsTable
+ navigable_item_name = _("Container")
+ navigation_kwarg_name = "container_name"
+ content_kwarg_name = "subfolder_path"
+ has_breadcrumb = True
+ breadcrumb_url = "horizon:project:containers:index"
diff --git a/openstack_dashboard/dashboards/project/containers/forms.py b/openstack_dashboard/dashboards/project/containers/forms.py
new file mode 100644
index 000000000..e02696e73
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/containers/forms.py
@@ -0,0 +1,164 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.core import validators
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import messages
+
+from openstack_dashboard import api
+from .tables import wrap_delimiter
+
+
+LOG = logging.getLogger(__name__)
+
+
+no_slash_validator = validators.RegexValidator(r'^(?u)[^/]+$',
+ _("Slash is not an allowed "
+ "character."),
+ code="noslash")
+
+
+class CreateContainer(forms.SelfHandlingForm):
+ parent = forms.CharField(max_length=255,
+ required=False,
+ widget=forms.HiddenInput)
+ name = forms.CharField(max_length=255,
+ label=_("Container Name"),
+ validators=[no_slash_validator])
+
+ def handle(self, request, data):
+ try:
+ if not data['parent']:
+ # Create a container
+ api.swift_create_container(request, data["name"])
+ messages.success(request, _("Container created successfully."))
+ else:
+ # Create a pseudo-folder
+ container, slash, remainder = data['parent'].partition("/")
+ remainder = remainder.rstrip("/")
+ subfolder_name = "/".join([bit for bit
+ in (remainder, data['name'])
+ if bit])
+ api.swift_create_subfolder(request,
+ container,
+ subfolder_name)
+ messages.success(request, _("Folder created successfully."))
+ return True
+ except:
+ exceptions.handle(request, _('Unable to create container.'))
+
+
+class UploadObject(forms.SelfHandlingForm):
+ path = forms.CharField(max_length=255,
+ required=False,
+ widget=forms.HiddenInput)
+ name = forms.CharField(max_length=255,
+ label=_("Object Name"),
+ validators=[no_slash_validator])
+ object_file = forms.FileField(label=_("File"), allow_empty_file=True)
+ container_name = forms.CharField(widget=forms.HiddenInput())
+
+ def handle(self, request, data):
+ object_file = self.files['object_file']
+ if data['path']:
+ object_path = "/".join([data['path'].rstrip("/"), data['name']])
+ else:
+ object_path = data['name']
+ try:
+ obj = api.swift_upload_object(request,
+ data['container_name'],
+ object_path,
+ object_file)
+ messages.success(request, _("Object was successfully uploaded."))
+ return obj
+ except:
+ exceptions.handle(request, _("Unable to upload object."))
+
+
+class CopyObject(forms.SelfHandlingForm):
+ new_container_name = forms.ChoiceField(label=_("Destination container"),
+ validators=[no_slash_validator])
+ path = forms.CharField(max_length=255, required=False)
+ new_object_name = forms.CharField(max_length=255,
+ label=_("Destination object name"),
+ validators=[no_slash_validator])
+ orig_container_name = forms.CharField(widget=forms.HiddenInput())
+ orig_object_name = forms.CharField(widget=forms.HiddenInput())
+
+ def __init__(self, *args, **kwargs):
+ containers = kwargs.pop('containers')
+ super(CopyObject, self).__init__(*args, **kwargs)
+ self.fields['new_container_name'].choices = containers
+
+ def handle(self, request, data):
+ index = "horizon:project:containers:index"
+ orig_container = data['orig_container_name']
+ orig_object = data['orig_object_name']
+ new_container = data['new_container_name']
+ new_object = data['new_object_name']
+ new_path = "%s%s" % (data['path'], new_object)
+
+ # Iteratively make sure all the directory markers exist.
+ if data['path']:
+ path_component = ""
+ for bit in [i for i in data['path'].split("/") if i]:
+ path_component += bit
+ try:
+ api.swift.swift_create_subfolder(request,
+ new_container,
+ path_component)
+ except:
+ redirect = reverse(index,
+ args=(wrap_delimiter(orig_container),))
+ exceptions.handle(request,
+ _("Unable to copy object."),
+ redirect=redirect)
+ path_component += "/"
+
+ # Now copy the object itself.
+ try:
+ api.swift_copy_object(request,
+ orig_container,
+ orig_object,
+ new_container,
+ new_path)
+ dest = "%s/%s" % (new_container, data['path'])
+ vals = {"dest": dest.rstrip("/"),
+ "orig": orig_object.split("/")[-1],
+ "new": new_object}
+ messages.success(request,
+ _('Copied "%(orig)s" to "%(dest)s" as "%(new)s".')
+ % vals)
+ return True
+ except exceptions.HorizonException, exc:
+ messages.error(request, exc)
+ raise exceptions.Http302(reverse(index,
+ args=[wrap_delimiter(orig_container)]))
+ except:
+ redirect = reverse(index, args=[wrap_delimiter(orig_container)])
+ exceptions.handle(request,
+ _("Unable to copy object."),
+ redirect=redirect)
diff --git a/openstack_dashboard/dashboards/project/containers/panel.py b/openstack_dashboard/dashboards/project/containers/panel.py
new file mode 100644
index 000000000..1f726d499
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/containers/panel.py
@@ -0,0 +1,33 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 Containers(horizon.Panel):
+ name = _("Containers")
+ slug = 'containers'
+ permissions = ('openstack.services.object-store',)
+
+dashboard.Project.register(Containers)
diff --git a/openstack_dashboard/dashboards/project/containers/tables.py b/openstack_dashboard/dashboards/project/containers/tables.py
new file mode 100644
index 000000000..8cb64a31a
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/containers/tables.py
@@ -0,0 +1,270 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.template.defaultfilters import filesizeformat
+from django.utils import http
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import tables
+
+from openstack_dashboard import api
+from openstack_dashboard.api import FOLDER_DELIMITER
+
+
+LOG = logging.getLogger(__name__)
+
+
+def wrap_delimiter(name):
+ if not name.endswith(FOLDER_DELIMITER):
+ return name + FOLDER_DELIMITER
+ return name
+
+
+class DeleteContainer(tables.DeleteAction):
+ data_type_singular = _("Container")
+ data_type_plural = _("Containers")
+ success_url = "horizon:project:containers:index"
+
+ def delete(self, request, obj_id):
+ api.swift_delete_container(request, obj_id)
+
+ def get_success_url(self, request=None):
+ """
+ Returns the URL to redirect to after a successful action.
+ """
+ current_container = self.table.kwargs.get("container_name", None)
+
+ # If the current_container is deleted, then redirect to the default
+ # completion url
+ if current_container in self.success_ids:
+ return self.success_url
+ return request.get_full_path()
+
+
+class CreateContainer(tables.LinkAction):
+ name = "create"
+ verbose_name = _("Create Container")
+ url = "horizon:project:containers:create"
+ classes = ("ajax-modal", "btn-create")
+
+
+class ListObjects(tables.LinkAction):
+ name = "list_objects"
+ verbose_name = _("View Container")
+ url = "horizon:project:containers:index"
+ classes = ("btn-list",)
+
+ def get_link_url(self, datum=None):
+ container_name = http.urlquote(datum.name)
+ args = (wrap_delimiter(container_name),)
+ return reverse(self.url, args=args)
+
+
+class UploadObject(tables.LinkAction):
+ name = "upload"
+ verbose_name = _("Upload Object")
+ url = "horizon:project:containers:object_upload"
+ classes = ("ajax-modal", "btn-upload")
+
+ def get_link_url(self, datum=None):
+ # Usable for both the container and object tables
+ if getattr(datum, 'container', datum):
+ # This is a container
+ container_name = http.urlquote(datum.name)
+ else:
+ # This is a table action, and we already have the container name
+ container_name = self.table.kwargs['container_name']
+ subfolders = self.table.kwargs.get('subfolder_path', '')
+ args = (http.urlquote(bit) for bit in
+ (container_name, subfolders) if bit)
+ return reverse(self.url, args=args)
+
+ def allowed(self, request, datum=None):
+ if self.table.kwargs.get('container_name', None):
+ return True
+ return False
+
+ def update(self, request, obj):
+ # This will only be called for the row, so we can remove the button
+ # styles meant for the table action version.
+ self.attrs = {'class': 'ajax-modal'}
+
+
+def get_size_used(container):
+ return filesizeformat(container.bytes)
+
+
+def get_container_link(container):
+ return reverse("horizon:project:containers:index",
+ args=(http.urlquote(wrap_delimiter(container.name)),))
+
+
+class ContainersTable(tables.DataTable):
+ name = tables.Column("name",
+ link=get_container_link,
+ verbose_name=_("Container Name"))
+
+ def get_object_id(self, container):
+ return container.name
+
+ class Meta:
+ name = "containers"
+ verbose_name = _("Containers")
+ table_actions = (CreateContainer,)
+ row_actions = (DeleteContainer,)
+ browser_table = "navigation"
+ footer = False
+
+
+class DeleteObject(tables.DeleteAction):
+ name = "delete_object"
+ data_type_singular = _("Object")
+ data_type_plural = _("Objects")
+ allowed_data_types = ("objects",)
+
+ def delete(self, request, obj_id):
+ obj = self.table.get_object_by_id(obj_id)
+ container_name = obj.container_name
+ api.swift_delete_object(request, container_name, obj_id)
+
+
+class DeleteSubfolder(DeleteObject):
+ name = "delete_subfolder"
+ data_type_singular = _("Folder")
+ data_type_plural = _("Folders")
+ allowed_data_types = ("subfolders",)
+
+
+class DeleteMultipleObjects(DeleteObject):
+ name = "delete_multiple_objects"
+ data_type_singular = _("Object")
+ data_type_plural = _("Objects")
+ allowed_data_types = ("subfolders", "objects",)
+
+
+class CopyObject(tables.LinkAction):
+ name = "copy"
+ verbose_name = _("Copy")
+ url = "horizon:project:containers:object_copy"
+ classes = ("ajax-modal", "btn-copy")
+ allowed_data_types = ("objects",)
+
+ def get_link_url(self, obj):
+ container_name = self.table.kwargs['container_name']
+ return reverse(self.url, args=(http.urlquote(container_name),
+ http.urlquote(obj.name)))
+
+
+class DownloadObject(tables.LinkAction):
+ name = "download"
+ verbose_name = _("Download")
+ url = "horizon:project:containers:object_download"
+ classes = ("btn-download",)
+ allowed_data_types = ("objects",)
+
+ def get_link_url(self, obj):
+ container_name = self.table.kwargs['container_name']
+ return reverse(self.url, args=(http.urlquote(container_name),
+ http.urlquote(obj.name)))
+
+
+class ObjectFilterAction(tables.FilterAction):
+ def _filtered_data(self, table, filter_string):
+ request = table.request
+ container = self.table.kwargs['container_name']
+ subfolder = self.table.kwargs['subfolder_path']
+ prefix = wrap_delimiter(subfolder) if subfolder else ''
+ self.filtered_data = api.swift_filter_objects(request,
+ filter_string,
+ container,
+ prefix=prefix)
+ return self.filtered_data
+
+ def filter_subfolders_data(self, table, objects, filter_string):
+ data = self._filtered_data(table, filter_string)
+ return [datum for datum in data if
+ datum.content_type == "application/directory"]
+
+ def filter_objects_data(self, table, objects, filter_string):
+ data = self._filtered_data(table, filter_string)
+ return [datum for datum in data if
+ datum.content_type != "application/directory"]
+
+ def allowed(self, request, datum=None):
+ if self.table.kwargs.get('container_name', None):
+ return True
+ return False
+
+
+def sanitize_name(name):
+ return name.split(FOLDER_DELIMITER)[-1]
+
+
+def get_size(obj):
+ if obj.bytes:
+ return filesizeformat(obj.bytes)
+
+
+def get_link_subfolder(subfolder):
+ container_name = subfolder.container_name
+ return reverse("horizon:project:containers:index",
+ args=(http.urlquote(wrap_delimiter(container_name)),
+ http.urlquote(wrap_delimiter(subfolder.name))))
+
+
+class CreateSubfolder(CreateContainer):
+ verbose_name = _("Create Folder")
+ url = "horizon:project:containers:create"
+
+ def get_link_url(self):
+ container = self.table.kwargs['container_name']
+ subfolders = self.table.kwargs['subfolder_path']
+ parent = FOLDER_DELIMITER.join((bit for bit in [container,
+ subfolders] if bit))
+ parent = parent.rstrip(FOLDER_DELIMITER)
+ return reverse(self.url, args=[http.urlquote(wrap_delimiter(parent))])
+
+ def allowed(self, request, datum=None):
+ if self.table.kwargs.get('container_name', None):
+ return True
+ return False
+
+
+class ObjectsTable(tables.DataTable):
+ name = tables.Column("name",
+ link=get_link_subfolder,
+ allowed_data_types=("subfolders",),
+ verbose_name=_("Object Name"),
+ filters=(sanitize_name,))
+
+ size = tables.Column(get_size, verbose_name=_('Size'))
+
+ def get_object_id(self, obj):
+ return obj.name
+
+ class Meta:
+ name = "objects"
+ verbose_name = _("Objects")
+ table_actions = (ObjectFilterAction, CreateSubfolder,
+ UploadObject, DeleteMultipleObjects)
+ row_actions = (DownloadObject, CopyObject, DeleteObject,
+ DeleteSubfolder)
+ data_types = ("subfolders", "objects")
+ browser_table = "content"
+ footer = False
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/_copy.html b/openstack_dashboard/dashboards/project/containers/templates/containers/_copy.html
new file mode 100644
index 000000000..3266a7bd8
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/containers/templates/containers/_copy.html
@@ -0,0 +1,24 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}copy_object_form{% endblock %}
+{% block form_action %}{% url horizon:project:containers:object_copy container_name object_name %}{% endblock %}
+
+{% block modal-header %}{% trans "Copy Object" %}: {{ object_name }}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "Make a new copy of an existing object to store in this or another container. You may also specify a path at which the new copy should live inside of the selected container." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Copy Object" %}" />
+ <a href="{% url horizon:project:containers:index container_name|add:'/' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/_create.html b/openstack_dashboard/dashboards/project/containers/templates/containers/_create.html
new file mode 100644
index 000000000..4b1e04195
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/containers/templates/containers/_create.html
@@ -0,0 +1,24 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}create_container_form{% endblock %}
+{% block form_action %}{% url horizon:project:containers:create %}{% endblock %}
+
+{% block modal-header %}{% trans "Create Container" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "A container is a storage compartment for your data and provides a way for you to organize your data. You can think of a container as a folder in Windows &reg; or a directory in UNIX &reg;. The primary difference between a container and these other file system concepts is that containers cannot be nested. You can, however, create an unlimited number of containers within your account. Data must be stored in a container so you must have at least one container defined in your account prior to uploading data." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Container" %}" />
+ <a href="{% url horizon:project:containers:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/_upload.html b/openstack_dashboard/dashboards/project/containers/templates/containers/_upload.html
new file mode 100644
index 000000000..503bc9778
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/containers/templates/containers/_upload.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}upload_object_form{% endblock %}
+{% block form_action %}{% url horizon:project:containers:object_upload container_name %}{% endblock %}
+{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
+
+{% block modal-header %}{% trans "Upload Object To Container" %}: {{ container_name }}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "An object is the basic storage entity and any optional metadata that represents the files you store in the OpenStack Object Storage system. When you upload data to OpenStack Object Storage, the data is stored as-is (no compression or encryption) and consists of a location (container), the object's name, and any metadata consisting of key/value pairs." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Upload Object" %}" />
+ <a href="{% url horizon:project:containers:index container_name|add:'/' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/copy.html b/openstack_dashboard/dashboards/project/containers/templates/containers/copy.html
new file mode 100644
index 000000000..d3568a496
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/containers/templates/containers/copy.html
@@ -0,0 +1,13 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Copy Object" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Copy Object") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'project/containers/_copy.html' %}
+{% endblock %}
+
+
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/create.html b/openstack_dashboard/dashboards/project/containers/templates/containers/create.html
new file mode 100644
index 000000000..bba31fccb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/containers/templates/containers/create.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Create Container{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Create Container") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include "project/containers/_create.html" %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/index.html b/openstack_dashboard/dashboards/project/containers/templates/containers/index.html
new file mode 100644
index 000000000..3779a8943
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/containers/templates/containers/index.html
@@ -0,0 +1,13 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Containers{% endblock %}
+
+{% block page_header %}
+ <div class='page-header'>
+ <h2>{% trans "Containers" %}
+ </div>
+{% endblock page_header %}
+
+{% block main %}
+ {{ swift_browser.render }}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/containers/templates/containers/upload.html b/openstack_dashboard/dashboards/project/containers/templates/containers/upload.html
new file mode 100644
index 000000000..4f8838172
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/containers/templates/containers/upload.html
@@ -0,0 +1,15 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Upload Object" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Upload Objects") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'project/containers/_upload.html' %}
+{% endblock %}
+
+
+
+
diff --git a/openstack_dashboard/dashboards/project/containers/tests.py b/openstack_dashboard/dashboards/project/containers/tests.py
new file mode 100644
index 000000000..91d76a848
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/containers/tests.py
@@ -0,0 +1,238 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 tempfile
+
+from django import http
+from django.core.files.uploadedfile import InMemoryUploadedFile
+from django.core.urlresolvers import reverse
+
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+from .tables import ContainersTable, ObjectsTable, wrap_delimiter
+from . import forms
+
+
+CONTAINER_INDEX_URL = reverse('horizon:project:containers:index')
+
+
+class SwiftTests(test.TestCase):
+ def test_index_no_container_selected(self):
+ containers = self.containers.list()
+ self.mox.StubOutWithMock(api, 'swift_get_containers')
+ api.swift_get_containers(IsA(http.HttpRequest), marker=None) \
+ .AndReturn((containers, False))
+ self.mox.ReplayAll()
+
+ res = self.client.get(CONTAINER_INDEX_URL)
+
+ self.assertTemplateUsed(res, 'project/containers/index.html')
+ self.assertIn('table', res.context)
+ resp_containers = res.context['table'].data
+ self.assertEqual(len(resp_containers), len(containers))
+
+ def test_delete_container(self):
+ container = self.containers.get(name=u"container_two\u6346")
+ self.mox.StubOutWithMock(api, 'swift_delete_container')
+ api.swift_delete_container(IsA(http.HttpRequest), container.name)
+ self.mox.ReplayAll()
+
+ action_string = u"containers__delete__%s" % container.name
+ form_data = {"action": action_string}
+ req = self.factory.post(CONTAINER_INDEX_URL, form_data)
+ table = ContainersTable(req, self.containers.list())
+ handled = table.maybe_handle()
+ self.assertEqual(handled['location'], CONTAINER_INDEX_URL)
+
+ def test_delete_container_nonempty(self):
+ container = self.containers.first()
+ self.mox.StubOutWithMock(api, 'swift_delete_container')
+ exc = self.exceptions.swift
+ exc.silence_logging = True
+ api.swift_delete_container(IsA(http.HttpRequest),
+ container.name).AndRaise(exc)
+ self.mox.ReplayAll()
+
+ action_string = u"containers__delete__%s" % container.name
+ form_data = {"action": action_string}
+ req = self.factory.post(CONTAINER_INDEX_URL, form_data)
+ table = ContainersTable(req, self.containers.list())
+ handled = table.maybe_handle()
+ self.assertEqual(handled['location'], CONTAINER_INDEX_URL)
+
+ def test_create_container_get(self):
+ res = self.client.get(reverse('horizon:project:containers:create'))
+ self.assertTemplateUsed(res, 'project/containers/create.html')
+
+ def test_create_container_post(self):
+ self.mox.StubOutWithMock(api, 'swift_create_container')
+ api.swift_create_container(IsA(http.HttpRequest),
+ self.containers.first().name)
+ self.mox.ReplayAll()
+
+ formData = {'name': self.containers.first().name,
+ 'method': forms.CreateContainer.__name__}
+ res = self.client.post(reverse('horizon:project:containers:create'),
+ formData)
+ url = reverse('horizon:project:containers:index',
+ args=[wrap_delimiter(self.containers.first().name)])
+ self.assertRedirectsNoFollow(res, url)
+
+ def test_index_container_selected(self):
+ self.mox.StubOutWithMock(api, 'swift_get_containers')
+ self.mox.StubOutWithMock(api, 'swift_get_objects')
+ containers = (self.containers.list(), False)
+ ret = (self.objects.list(), False)
+ api.swift_get_containers(IsA(http.HttpRequest),
+ marker=None).AndReturn(containers)
+ api.swift_get_objects(IsA(http.HttpRequest),
+ self.containers.first().name,
+ marker=None,
+ prefix=None).AndReturn(ret)
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:project:containers:index',
+ args=[wrap_delimiter(self.containers
+ .first()
+ .name)]))
+ self.assertTemplateUsed(res, 'project/containers/index.html')
+ # UTF8 encoding here to ensure there aren't problems with Nose output.
+ expected = [obj.name.encode('utf8') for obj in self.objects.list()]
+ self.assertQuerysetEqual(res.context['objects_table'].data,
+ expected,
+ lambda obj: obj.name.encode('utf8'))
+
+ def test_upload(self):
+ container = self.containers.first()
+ obj = self.objects.first()
+ OBJECT_DATA = 'objectData'
+
+ temp_file = tempfile.TemporaryFile()
+ temp_file.write(OBJECT_DATA)
+ temp_file.flush()
+ temp_file.seek(0)
+
+ self.mox.StubOutWithMock(api, 'swift_upload_object')
+ api.swift_upload_object(IsA(http.HttpRequest),
+ container.name,
+ obj.name,
+ IsA(InMemoryUploadedFile)).AndReturn(obj)
+ self.mox.ReplayAll()
+
+ upload_url = reverse('horizon:project:containers:object_upload',
+ args=[container.name])
+
+ res = self.client.get(upload_url)
+ self.assertTemplateUsed(res, 'project/containers/upload.html')
+
+ res = self.client.get(upload_url)
+ self.assertContains(res, 'enctype="multipart/form-data"')
+
+ formData = {'method': forms.UploadObject.__name__,
+ 'container_name': container.name,
+ 'name': obj.name,
+ 'object_file': temp_file}
+ res = self.client.post(upload_url, formData)
+
+ index_url = reverse('horizon:project:containers:index',
+ args=[wrap_delimiter(container.name)])
+ self.assertRedirectsNoFollow(res, index_url)
+
+ # Test invalid filename
+ formData['name'] = "contains/a/slash"
+ res = self.client.post(upload_url, formData)
+ self.assertNoMessages()
+ self.assertContains(res, "Slash is not an allowed character.")
+
+ def test_delete(self):
+ container = self.containers.first()
+ obj = self.objects.first()
+ index_url = reverse('horizon:project:containers:index',
+ args=[wrap_delimiter(container.name)])
+ self.mox.StubOutWithMock(api, 'swift_delete_object')
+ api.swift_delete_object(IsA(http.HttpRequest),
+ container.name,
+ obj.name)
+ self.mox.ReplayAll()
+
+ action_string = "objects__delete_object__%s" % obj.name
+ form_data = {"action": action_string}
+ req = self.factory.post(index_url, form_data)
+ kwargs = {"container_name": container.name}
+ table = ObjectsTable(req, self.objects.list(), **kwargs)
+ handled = table.maybe_handle()
+ self.assertEqual(handled['location'], index_url)
+
+ def test_download(self):
+ container = self.containers.first()
+ obj = self.objects.first()
+
+ self.mox.StubOutWithMock(api.swift, 'swift_get_object')
+ api.swift.swift_get_object(IsA(http.HttpRequest),
+ container.name,
+ obj.name).AndReturn(obj)
+ self.mox.ReplayAll()
+
+ download_url = reverse('horizon:project:containers:object_download',
+ args=[container.name, obj.name])
+ res = self.client.get(download_url)
+ self.assertEqual(res.content, obj.data)
+ self.assertTrue(res.has_header('Content-Disposition'))
+
+ def test_copy_index(self):
+ self.mox.StubOutWithMock(api, 'swift_get_containers')
+ ret = (self.containers.list(), False)
+ api.swift_get_containers(IsA(http.HttpRequest)).AndReturn(ret)
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:project:containers:object_copy',
+ args=[self.containers.first().name,
+ self.objects.first().name]))
+ self.assertTemplateUsed(res, 'project/containers/copy.html')
+
+ def test_copy(self):
+ container_1 = self.containers.get(name=u"container_one\u6346")
+ container_2 = self.containers.get(name=u"container_two\u6346")
+ obj = self.objects.first()
+
+ self.mox.StubOutWithMock(api, 'swift_get_containers')
+ self.mox.StubOutWithMock(api, 'swift_copy_object')
+ ret = (self.containers.list(), False)
+ api.swift_get_containers(IsA(http.HttpRequest)).AndReturn(ret)
+ api.swift_copy_object(IsA(http.HttpRequest),
+ container_1.name,
+ obj.name,
+ container_2.name,
+ obj.name)
+ self.mox.ReplayAll()
+
+ formData = {'method': forms.CopyObject.__name__,
+ 'new_container_name': container_2.name,
+ 'new_object_name': obj.name,
+ 'orig_container_name': container_1.name,
+ 'orig_object_name': obj.name}
+ copy_url = reverse('horizon:project:containers:object_copy',
+ args=[container_1.name, obj.name])
+ res = self.client.post(copy_url, formData)
+ index_url = reverse('horizon:project:containers:index',
+ args=[wrap_delimiter(container_2.name)])
+ self.assertRedirectsNoFollow(res, index_url)
diff --git a/openstack_dashboard/dashboards/project/containers/urls.py b/openstack_dashboard/dashboards/project/containers/urls.py
new file mode 100644
index 000000000..9965a9dd0
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/containers/urls.py
@@ -0,0 +1,50 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import patterns, url
+
+from .views import CreateView, UploadView, CopyView, ContainerView
+
+
+VIEW_MOD = 'openstack_dashboard.dashboards.project.containers.views'
+
+# Swift containers and objects.
+urlpatterns = patterns(VIEW_MOD,
+ url(r'^((?P<container_name>.+?)/)?(?P<subfolder_path>(.+/)+)?$',
+ ContainerView.as_view(), name='index'),
+
+ url(r'^(?P<container_name>(.+/)+)?create$',
+ CreateView.as_view(),
+ name='create'),
+
+ url(r'^(?P<container_name>.+?)/(?P<subfolder_path>(.+/)+)?upload$',
+ UploadView.as_view(),
+ name='object_upload'),
+
+ url(r'^(?P<container_name>[^/]+)/'
+ r'(?P<subfolder_path>(.+/)+)?'
+ r'(?P<object_name>.+)/copy$',
+ CopyView.as_view(),
+ name='object_copy'),
+
+ url(r'^(?P<container_name>[^/]+)/(?P<object_path>.+)/download$',
+ 'object_download',
+ name='object_download')
+)
diff --git a/openstack_dashboard/dashboards/project/containers/views.py b/openstack_dashboard/dashboards/project/containers/views.py
new file mode 100644
index 000000000..5b0273e2c
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/containers/views.py
@@ -0,0 +1,218 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.
+
+"""
+Views for managing Swift containers.
+"""
+import os
+
+from django import http
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import browsers
+from horizon import exceptions
+from horizon import forms
+
+from openstack_dashboard import api
+from openstack_dashboard.api import FOLDER_DELIMITER
+from .browsers import ContainerBrowser
+from .forms import CreateContainer, UploadObject, CopyObject
+from .tables import wrap_delimiter
+
+
+class ContainerView(browsers.ResourceBrowserView):
+ browser_class = ContainerBrowser
+ template_name = "project/containers/index.html"
+
+ def get_containers_data(self):
+ containers = []
+ self._more = None
+ marker = self.request.GET.get('marker', None)
+ try:
+ containers, self._more = api.swift_get_containers(self.request,
+ marker=marker)
+ except:
+ msg = _('Unable to retrieve container list.')
+ exceptions.handle(self.request, msg)
+ return containers
+
+ @property
+ def objects(self):
+ """ Returns a list of objects given the subfolder's path.
+
+ The path is from the kwargs of the request.
+ """
+ if not hasattr(self, "_objects"):
+ objects = []
+ self._more = None
+ marker = self.request.GET.get('marker', None)
+ container_name = self.kwargs['container_name']
+ subfolder = self.kwargs['subfolder_path']
+ prefix = None
+ if container_name:
+ self.navigation_selection = True
+ if subfolder:
+ prefix = subfolder
+ try:
+ objects, self._more = api.swift_get_objects(self.request,
+ container_name,
+ marker=marker,
+ prefix=prefix)
+ except:
+ self._more = None
+ objects = []
+ msg = _('Unable to retrieve object list.')
+ exceptions.handle(self.request, msg)
+ self._objects = objects
+ return self._objects
+
+ def is_subdir(self, item):
+ return getattr(item, "content_type", None) == "application/directory"
+
+ def get_objects_data(self):
+ """ Returns a list of objects within the current folder. """
+ filtered_objects = [item for item in self.objects
+ if not self.is_subdir(item)]
+ return filtered_objects
+
+ def get_subfolders_data(self):
+ """ Returns a list of subfolders within the current folder. """
+ filtered_objects = [item for item in self.objects
+ if self.is_subdir(item)]
+ return filtered_objects
+
+ def get_context_data(self, **kwargs):
+ context = super(ContainerView, self).get_context_data(**kwargs)
+ context['container_name'] = self.kwargs["container_name"]
+ context['subfolders'] = []
+ if self.kwargs["subfolder_path"]:
+ (parent, slash, folder) = self.kwargs["subfolder_path"].\
+ strip('/').rpartition('/')
+ while folder:
+ path = "%s%s%s/" % (parent, slash, folder)
+ context['subfolders'].insert(0, (folder, path))
+ (parent, slash, folder) = parent.rpartition('/')
+ return context
+
+
+class CreateView(forms.ModalFormView):
+ form_class = CreateContainer
+ template_name = 'project/containers/create.html'
+ success_url = "horizon:project:containers:index"
+
+ def get_success_url(self):
+ parent = self.request.POST.get('parent', None)
+ if parent:
+ container, slash, remainder = parent.partition(FOLDER_DELIMITER)
+ container += FOLDER_DELIMITER
+ if remainder and not remainder.endswith(FOLDER_DELIMITER):
+ remainder = "".join([remainder, FOLDER_DELIMITER])
+ return reverse(self.success_url, args=(container, remainder))
+ else:
+ return reverse(self.success_url, args=[self.request.POST['name'] +
+ FOLDER_DELIMITER])
+
+ def get_initial(self):
+ initial = super(CreateView, self).get_initial()
+ initial['parent'] = self.kwargs['container_name']
+ return initial
+
+
+class UploadView(forms.ModalFormView):
+ form_class = UploadObject
+ template_name = 'project/containers/upload.html'
+ success_url = "horizon:project:containers:index"
+
+ def get_success_url(self):
+ container_name = self.request.POST['container_name']
+ return reverse(self.success_url,
+ args=(wrap_delimiter(container_name),
+ self.request.POST.get('path', '')))
+
+ def get_initial(self):
+ return {"container_name": self.kwargs["container_name"],
+ "path": self.kwargs['subfolder_path']}
+
+ def get_context_data(self, **kwargs):
+ context = super(UploadView, self).get_context_data(**kwargs)
+ context['container_name'] = self.kwargs["container_name"]
+ return context
+
+
+def object_download(request, container_name, object_path):
+ try:
+ obj = api.swift.swift_get_object(request, container_name, object_path)
+ except:
+ redirect = reverse("horizon:project:containers:index")
+ exceptions.handle(request,
+ _("Unable to retrieve object."),
+ redirect=redirect)
+ # Add the original file extension back on if it wasn't preserved in the
+ # name given to the object.
+ filename = object_path.rsplit(FOLDER_DELIMITER)[-1]
+ if not os.path.splitext(obj.name)[1] and obj.orig_name:
+ name, ext = os.path.splitext(obj.orig_name)
+ filename = "%s%s" % (filename, ext)
+ response = http.HttpResponse()
+ safe_name = filename.replace(",", "").encode('utf-8')
+ response['Content-Disposition'] = 'attachment; filename=%s' % safe_name
+ response['Content-Type'] = 'application/octet-stream'
+ response.write(obj.data)
+ return response
+
+
+class CopyView(forms.ModalFormView):
+ form_class = CopyObject
+ template_name = 'project/containers/copy.html'
+ success_url = "horizon:project:containers:index"
+
+ def get_success_url(self):
+ new_container_name = self.request.POST['new_container_name']
+ return reverse(self.success_url,
+ args=(wrap_delimiter(new_container_name),
+ self.request.POST.get('path', '')))
+
+ def get_form_kwargs(self):
+ kwargs = super(CopyView, self).get_form_kwargs()
+ try:
+ containers = api.swift_get_containers(self.request)
+ except:
+ redirect = reverse("horizon:project:containers:index")
+ exceptions.handle(self.request,
+ _('Unable to list containers.'),
+ redirect=redirect)
+ kwargs['containers'] = [(c.name, c.name) for c in containers[0]]
+ return kwargs
+
+ def get_initial(self):
+ path = self.kwargs["subfolder_path"]
+ orig = "%s%s" % (path or '', self.kwargs["object_name"])
+ return {"new_container_name": self.kwargs["container_name"],
+ "orig_container_name": self.kwargs["container_name"],
+ "orig_object_name": orig,
+ "path": path,
+ "new_object_name": "%s copy" % self.kwargs["object_name"]}
+
+ def get_context_data(self, **kwargs):
+ context = super(CopyView, self).get_context_data(**kwargs)
+ context['container_name'] = self.kwargs["container_name"]
+ context['object_name'] = self.kwargs["object_name"]
+ return context
diff --git a/openstack_dashboard/dashboards/project/dashboard.py b/openstack_dashboard/dashboards/project/dashboard.py
new file mode 100644
index 000000000..691d7fa41
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/dashboard.py
@@ -0,0 +1,47 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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
+
+
+class BasePanels(horizon.PanelGroup):
+ slug = "compute"
+ name = _("Manage Compute")
+ panels = ('overview',
+ 'instances',
+ 'volumes',
+ 'images_and_snapshots',
+ 'access_and_security',
+ 'networks')
+
+
+class ObjectStorePanels(horizon.PanelGroup):
+ slug = "object_store"
+ name = _("Object Store")
+ panels = ('containers',)
+
+
+class Project(horizon.Dashboard):
+ name = _("Project")
+ slug = "project"
+ panels = (BasePanels, ObjectStorePanels)
+ default_panel = 'overview'
+ supports_tenants = True
+
+
+horizon.register(Project)
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/__init__.py b/openstack_dashboard/dashboards/project/images_and_snapshots/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/__init__.py
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/images/__init__.py b/openstack_dashboard/dashboards/project/images_and_snapshots/images/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/images/__init__.py
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/images/forms.py b/openstack_dashboard/dashboards/project/images_and_snapshots/images/forms.py
new file mode 100644
index 000000000..a91f67671
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/images/forms.py
@@ -0,0 +1,165 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.
+
+"""
+Views for managing images.
+"""
+
+import logging
+
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import messages
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateImageForm(forms.SelfHandlingForm):
+ name = forms.CharField(max_length="255", label=_("Name"), required=True)
+ copy_from = forms.CharField(max_length="255",
+ label=_("Image Location"),
+ help_text=_("An external (HTTP) URL to load "
+ "the image from."),
+ required=True)
+ disk_format = forms.ChoiceField(label=_('Format'),
+ required=True,
+ choices=[('', ''),
+ ('aki',
+ _('AKI - Amazon Kernel '
+ 'Image')),
+ ('ami',
+ _('AMI - Amazon Machine '
+ 'Image')),
+ ('ari',
+ _('ARI - Amazon Ramdisk '
+ 'Image')),
+ ('iso',
+ _('ISO - Optical Disk Image')),
+ ('qcow2',
+ _('QCOW2 - QEMU Emulator')),
+ ('raw', 'Raw'),
+ ('vdi', 'VDI'),
+ ('vhd', 'VHD'),
+ ('vmdk', 'VMDK')],
+ widget=forms.Select(attrs={'class':
+ 'switchable'}))
+ minimum_disk = forms.IntegerField(label=_("Minimum Disk (GB)"),
+ help_text=_('The minimum disk size'
+ ' required to boot the'
+ ' image. If unspecified, this'
+ ' value defaults to 0'
+ ' (no minimum).'),
+ required=False)
+ minimum_ram = forms.IntegerField(label=_("Minimum Ram (MB)"),
+ help_text=_('The minimum disk size'
+ ' required to boot the'
+ ' image. If unspecified, this'
+ ' value defaults to 0 (no'
+ ' minimum).'),
+ required=False)
+ is_public = forms.BooleanField(label=_("Public"), required=False)
+
+ def handle(self, request, data):
+ # Glance does not really do anything with container_format at the
+ # moment. It requires it is set to the same disk_format for the three
+ # Amazon image types, otherwise it just treats them as 'bare.' As such
+ # we will just set that to be that here instead of bothering the user
+ # with asking them for information we can already determine.
+ if data['disk_format'] in ('ami', 'aki', 'ari',):
+ container_format = data['disk_format']
+ else:
+ container_format = 'bare'
+
+ meta = {'is_public': data['is_public'],
+ 'disk_format': data['disk_format'],
+ 'container_format': container_format,
+ 'copy_from': data['copy_from'],
+ 'min_disk': (data['minimum_disk'] or 0),
+ 'min_ram': (data['minimum_ram'] or 0),
+ 'name': data['name']}
+
+ try:
+ image = api.glance.image_create(request, **meta)
+ messages.success(request,
+ _('Your image %s has been queued for creation.' %
+ data['name']))
+ return image
+ except:
+ exceptions.handle(request, _('Unable to create new image.'))
+
+
+class UpdateImageForm(forms.SelfHandlingForm):
+ image_id = forms.CharField(widget=forms.HiddenInput())
+ name = forms.CharField(max_length="255", label=_("Name"))
+ kernel = forms.CharField(max_length="36", label=_("Kernel ID"),
+ required=False,
+ widget=forms.TextInput(
+ attrs={'readonly': 'readonly'}
+ ))
+ ramdisk = forms.CharField(max_length="36", label=_("Ramdisk ID"),
+ required=False,
+ widget=forms.TextInput(
+ attrs={'readonly': 'readonly'}
+ ))
+ architecture = forms.CharField(label=_("Architecture"), required=False,
+ widget=forms.TextInput(
+ attrs={'readonly': 'readonly'}
+ ))
+ disk_format = forms.CharField(label=_("Format"),
+ widget=forms.TextInput(
+ attrs={'readonly': 'readonly'}
+ ))
+ public = forms.BooleanField(label=_("Public"), required=False)
+
+ def handle(self, request, data):
+ image_id = data['image_id']
+ error_updating = _('Unable to update image "%s".')
+
+ if data['disk_format'] in ['aki', 'ari', 'ami']:
+ container_format = data['disk_format']
+ else:
+ container_format = 'bare'
+
+ meta = {'is_public': data['public'],
+ 'disk_format': data['disk_format'],
+ 'container_format': container_format,
+ 'name': data['name'],
+ 'properties': {}}
+ if data['kernel']:
+ meta['properties']['kernel_id'] = data['kernel']
+ if data['ramdisk']:
+ meta['properties']['ramdisk_id'] = data['ramdisk']
+ if data['architecture']:
+ meta['properties']['architecture'] = data['architecture']
+ # Ensure we do not delete properties that have already been
+ # set on an image.
+ meta['purge_props'] = False
+
+ try:
+ image = api.image_update(request, image_id, **meta)
+ messages.success(request, _('Image was successfully updated.'))
+ return image
+ except:
+ exceptions.handle(request, error_updating % image_id)
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/images/tables.py b/openstack_dashboard/dashboards/project/images_and_snapshots/images/tables.py
new file mode 100644
index 000000000..72e3aefaf
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/images/tables.py
@@ -0,0 +1,135 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.template import defaultfilters as filters
+from django.utils.http import urlencode
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import tables
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class LaunchImage(tables.LinkAction):
+ name = "launch_image"
+ verbose_name = _("Launch")
+ url = "horizon:project:instances:launch"
+ classes = ("btn-launch", "ajax-modal")
+
+ def get_link_url(self, datum):
+ base_url = reverse(self.url)
+ params = urlencode({"source_type": "image_id",
+ "source_id": self.table.get_object_id(datum)})
+ return "?".join([base_url, params])
+
+
+class DeleteImage(tables.DeleteAction):
+ data_type_singular = _("Image")
+ data_type_plural = _("Images")
+
+ def allowed(self, request, image=None):
+ if image:
+ return image.owner == request.user.tenant_id
+ # Return True to allow table-level bulk delete action to appear.
+ return True
+
+ def delete(self, request, obj_id):
+ api.image_delete(request, obj_id)
+
+
+class CreateImage(tables.LinkAction):
+ name = "create"
+ verbose_name = _("Create Image")
+ url = "horizon:project:images_and_snapshots:images:create"
+ classes = ("ajax-modal", "btn-create")
+
+
+class EditImage(tables.LinkAction):
+ name = "edit"
+ verbose_name = _("Edit")
+ url = "horizon:project:images_and_snapshots:images:update"
+ classes = ("ajax-modal", "btn-edit")
+
+ def allowed(self, request, image=None):
+ if image:
+ return image.status in ("active",) and \
+ image.owner == request.user.tenant_id
+ # We don't have bulk editing, so if there isn't an image that's
+ # authorized, don't allow the action.
+ return False
+
+
+def get_image_type(image):
+ return getattr(image, "properties", {}).get("image_type", _("Image"))
+
+
+def get_format(image):
+ format = getattr(image, "disk_format", "")
+ # The "container_format" attribute can actually be set to None,
+ # which will raise an error if you call upper() on it.
+ if format is not None:
+ return format.upper()
+
+
+class UpdateRow(tables.Row):
+ ajax = True
+
+ def get_data(self, request, image_id):
+ image = api.image_get(request, image_id)
+ return image
+
+
+class ImagesTable(tables.DataTable):
+ STATUS_CHOICES = (
+ ("active", True),
+ ("saving", None),
+ ("queued", None),
+ ("pending_delete", None),
+ ("killed", False),
+ ("deleted", False),
+ )
+ name = tables.Column("name",
+ link=("horizon:project:images_and_snapshots:"
+ "images:detail"),
+ verbose_name=_("Image Name"))
+ image_type = tables.Column(get_image_type,
+ verbose_name=_("Type"),
+ filters=(filters.title,))
+ status = tables.Column("status",
+ filters=(filters.title,),
+ verbose_name=_("Status"),
+ status=True,
+ status_choices=STATUS_CHOICES)
+ public = tables.Column("is_public",
+ verbose_name=_("Public"),
+ empty_value=False,
+ filters=(filters.yesno, filters.capfirst))
+ disk_format = tables.Column(get_format, verbose_name=_("Format"))
+
+ class Meta:
+ name = "images"
+ row_class = UpdateRow
+ status_columns = ["status"]
+ verbose_name = _("Images")
+ table_actions = (CreateImage, DeleteImage,)
+ row_actions = (LaunchImage, EditImage, DeleteImage,)
+ pagination_param = "image_marker"
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/images/tabs.py b/openstack_dashboard/dashboards/project/images_and_snapshots/images/tabs.py
new file mode 100644
index 000000000..fefc6816b
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/images/tabs.py
@@ -0,0 +1,45 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tabs
+
+from openstack_dashboard import api
+
+
+class OverviewTab(tabs.Tab):
+ name = _("Overview")
+ slug = "overview"
+ template_name = "project/images_and_snapshots/images/_detail_overview.html"
+
+ def get_context_data(self, request):
+ image_id = self.tab_group.kwargs['image_id']
+ try:
+ image = api.glance.image_get(self.request, image_id)
+ except:
+ redirect = reverse('horizon:project:images_and_snapshots:index')
+ exceptions.handle(request,
+ _('Unable to retrieve image details.'),
+ redirect=redirect)
+ return {'image': image}
+
+
+class ImageDetailTabs(tabs.TabGroup):
+ slug = "image_details"
+ tabs = (OverviewTab,)
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/images/tests.py b/openstack_dashboard/dashboards/project/images_and_snapshots/images/tests.py
new file mode 100644
index 000000000..4d147b3ea
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/images/tests.py
@@ -0,0 +1,96 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 import http
+from django.core.urlresolvers import reverse
+
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+IMAGES_INDEX_URL = reverse('horizon:project:images_and_snapshots:index')
+
+
+class ImageViewTests(test.TestCase):
+ def test_image_create_get(self):
+ url = reverse('horizon:project:images_and_snapshots:images:create')
+ res = self.client.get(url)
+ self.assertTemplateUsed(res,
+ 'project/images_and_snapshots/images/create.html')
+
+ @test.create_stubs({api.glance: ('image_create',)})
+ def test_image_create_post(self):
+ data = {
+ 'name': u'Ubuntu 11.10',
+ 'copy_from': u'http://cloud-images.ubuntu.com/releases/'
+ u'oneiric/release/ubuntu-11.10-server-cloudimg'
+ u'-amd64-disk1.img',
+ 'disk_format': u'qcow2',
+ 'minimum_disk': 15,
+ 'minimum_ram': 512,
+ 'is_public': 1,
+ 'method': 'CreateImageForm'}
+
+ api.glance.image_create(IsA(http.HttpRequest),
+ container_format="bare",
+ copy_from=data['copy_from'],
+ disk_format=data['disk_format'],
+ is_public=True,
+ min_disk=data['minimum_disk'],
+ min_ram=data['minimum_ram'],
+ name=data['name']). \
+ AndReturn(self.images.first())
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:images_and_snapshots:images:create')
+ res = self.client.post(url, data)
+
+ self.assertNoFormErrors(res)
+ self.assertEqual(res.status_code, 302)
+
+ @test.create_stubs({api.glance: ('image_get',)})
+ def test_image_detail_get(self):
+ image = self.images.first()
+
+ api.glance.image_get(IsA(http.HttpRequest), str(image.id)) \
+ .AndReturn(self.images.first())
+ self.mox.ReplayAll()
+
+ res = self.client.get(
+ reverse('horizon:project:images_and_snapshots:images:detail',
+ args=[image.id]))
+ self.assertTemplateUsed(res,
+ 'project/images_and_snapshots/images/detail.html')
+ self.assertEqual(res.context['image'].name, image.name)
+
+ @test.create_stubs({api.glance: ('image_get',)})
+ def test_image_detail_get_with_exception(self):
+ image = self.images.first()
+
+ api.glance.image_get(IsA(http.HttpRequest), str(image.id)) \
+ .AndRaise(self.exceptions.glance)
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:images_and_snapshots:images:detail',
+ args=[image.id])
+ res = self.client.get(url)
+ self.assertRedirectsNoFollow(res, IMAGES_INDEX_URL)
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/images/urls.py b/openstack_dashboard/dashboards/project/images_and_snapshots/images/urls.py
new file mode 100644
index 000000000..6e990c925
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/images/urls.py
@@ -0,0 +1,34 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import patterns, url
+
+from .views import UpdateView, DetailView, CreateView
+
+
+VIEWS_MOD = ('openstack_dashboard.dashboards.project'
+ '.images_and_snapshots.images.views')
+
+
+urlpatterns = patterns(VIEWS_MOD,
+ url(r'^create/$', CreateView.as_view(), name='create'),
+ url(r'^(?P<image_id>[^/]+)/update/$', UpdateView.as_view(), name='update'),
+ url(r'^(?P<image_id>[^/]+)/$', DetailView.as_view(), name='detail'),
+)
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/images/views.py b/openstack_dashboard/dashboards/project/images_and_snapshots/images/views.py
new file mode 100644
index 000000000..929f9b7f3
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/images/views.py
@@ -0,0 +1,84 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.
+
+"""
+Views for managing images.
+"""
+
+import logging
+
+from django.core.urlresolvers import reverse, reverse_lazy
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import tabs
+
+from openstack_dashboard import api
+from .forms import UpdateImageForm
+from .forms import CreateImageForm
+from .tabs import ImageDetailTabs
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateView(forms.ModalFormView):
+ form_class = CreateImageForm
+ template_name = 'project/images_and_snapshots/images/create.html'
+ context_object_name = 'image'
+ success_url = reverse_lazy("horizon:project:images_and_snapshots:index")
+
+
+class UpdateView(forms.ModalFormView):
+ form_class = UpdateImageForm
+ template_name = 'project/images_and_snapshots/images/update.html'
+ success_url = reverse_lazy("horizon:project:images_and_snapshots:index")
+
+ def get_object(self):
+ if not hasattr(self, "_object"):
+ try:
+ self._object = api.image_get(self.request,
+ self.kwargs['image_id'])
+ except:
+ msg = _('Unable to retrieve image.')
+ url = reverse('horizon:project:images_and_snapshots:index')
+ exceptions.handle(self.request, msg, redirect=url)
+ return self._object
+
+ def get_context_data(self, **kwargs):
+ context = super(UpdateView, self).get_context_data(**kwargs)
+ context['image'] = self.get_object()
+ return context
+
+ def get_initial(self):
+ image = self.get_object()
+ return {'image_id': self.kwargs['image_id'],
+ 'name': image.name,
+ 'kernel': image.properties.get('kernel_id', ''),
+ 'ramdisk': image.properties.get('ramdisk_id', ''),
+ 'architecture': image.properties.get('architecture', ''),
+ 'disk_format': image.disk_format,
+ 'public': image.is_public == "True"}
+
+
+class DetailView(tabs.TabView):
+ tab_group_class = ImageDetailTabs
+ template_name = 'project/images_and_snapshots/images/detail.html'
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/panel.py b/openstack_dashboard/dashboards/project/images_and_snapshots/panel.py
new file mode 100644
index 000000000..9746bb82f
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/panel.py
@@ -0,0 +1,30 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+# Copyright 2012 OpenStack LLC
+#
+# 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 ImagesAndSnapshots(horizon.Panel):
+ name = _("Images & Snapshots")
+ slug = 'images_and_snapshots'
+
+
+dashboard.Project.register(ImagesAndSnapshots)
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/__init__.py b/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/__init__.py
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/forms.py b/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/forms.py
new file mode 100644
index 000000000..5b950ad8f
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/forms.py
@@ -0,0 +1,57 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import messages
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateSnapshot(forms.SelfHandlingForm):
+ instance_id = forms.CharField(label=_("Instance ID"),
+ widget=forms.HiddenInput(),
+ required=False)
+ name = forms.CharField(max_length="20", label=_("Snapshot Name"))
+
+ def handle(self, request, data):
+ try:
+ snapshot = api.snapshot_create(request,
+ data['instance_id'],
+ data['name'])
+ # NOTE(gabriel): This API call is only to display a pretty name.
+ instance = api.server_get(request, data['instance_id'])
+ vals = {"name": data['name'], "inst": instance.name}
+ messages.success(request, _('Snapshot "%(name)s" created for '
+ 'instance "%(inst)s"') % vals)
+ return snapshot
+ except:
+ redirect = reverse("horizon:project:instances:index")
+ exceptions.handle(request,
+ _('Unable to create snapshot.'),
+ redirect=redirect)
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/tables.py b/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/tables.py
new file mode 100644
index 000000000..8355c2f4b
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/tables.py
@@ -0,0 +1,60 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.utils.http import urlencode
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import tables
+
+from ..images.tables import ImagesTable, EditImage, DeleteImage, UpdateRow
+
+
+LOG = logging.getLogger(__name__)
+
+
+class LaunchSnapshot(tables.LinkAction):
+ name = "launch_snapshot"
+ verbose_name = _("Launch")
+ url = "horizon:project:instances:launch"
+ classes = ("btn-launch", "ajax-modal")
+
+ def get_link_url(self, datum):
+ base_url = reverse(self.url)
+ params = urlencode({"source_type": "instance_snapshot_id",
+ "source_id": self.table.get_object_id(datum)})
+ return "?".join([base_url, params])
+
+ def allowed(self, request, snapshot):
+ return snapshot.status in ("active",)
+
+
+class DeleteSnapshot(DeleteImage):
+ data_type_singular = _("Snapshot")
+ data_type_plural = _("Snapshots")
+
+
+class SnapshotsTable(ImagesTable):
+ class Meta:
+ name = "snapshots"
+ verbose_name = _("Instance Snapshots")
+ table_actions = (DeleteSnapshot,)
+ row_actions = (LaunchSnapshot, EditImage, DeleteSnapshot)
+ pagination_param = "snapshot_marker"
+ row_class = UpdateRow
+ status_columns = ["status"]
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/tests.py b/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/tests.py
new file mode 100644
index 000000000..acef40cbb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/tests.py
@@ -0,0 +1,98 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 import http
+from django.core.urlresolvers import reverse
+
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+INDEX_URL = reverse('horizon:project:images_and_snapshots:index')
+
+
+class SnapshotsViewTests(test.TestCase):
+ def test_create_snapshot_get(self):
+ server = self.servers.first()
+ self.mox.StubOutWithMock(api, 'server_get')
+ api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:images_and_snapshots:snapshots:create',
+ args=[server.id])
+ res = self.client.get(url)
+ self.assertTemplateUsed(res,
+ 'project/images_and_snapshots/snapshots/create.html')
+
+ def test_create_get_server_exception(self):
+ server = self.servers.first()
+ self.mox.StubOutWithMock(api, 'server_get')
+ api.server_get(IsA(http.HttpRequest), server.id) \
+ .AndRaise(self.exceptions.nova)
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:images_and_snapshots:snapshots:create',
+ args=[server.id])
+ res = self.client.get(url)
+ redirect = reverse("horizon:project:instances:index")
+ self.assertRedirectsNoFollow(res, redirect)
+
+ def test_create_snapshot_post(self):
+ server = self.servers.first()
+ snapshot = self.snapshots.first()
+
+ self.mox.StubOutWithMock(api, 'server_get')
+ self.mox.StubOutWithMock(api, 'snapshot_create')
+ api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
+ api.snapshot_create(IsA(http.HttpRequest), server.id, snapshot.name) \
+ .AndReturn(snapshot)
+ self.mox.ReplayAll()
+
+ formData = {'method': 'CreateSnapshot',
+ 'tenant_id': self.tenant.id,
+ 'instance_id': server.id,
+ 'name': snapshot.name}
+ url = reverse('horizon:project:images_and_snapshots:snapshots:create',
+ args=[server.id])
+ res = self.client.post(url, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ def test_create_snapshot_post_exception(self):
+ server = self.servers.first()
+ snapshot = self.snapshots.first()
+
+ self.mox.StubOutWithMock(api, 'server_get')
+ self.mox.StubOutWithMock(api, 'snapshot_create')
+ api.snapshot_create(IsA(http.HttpRequest), server.id, snapshot.name) \
+ .AndRaise(self.exceptions.nova)
+ self.mox.ReplayAll()
+
+ formData = {'method': 'CreateSnapshot',
+ 'tenant_id': self.tenant.id,
+ 'instance_id': server.id,
+ 'name': snapshot.name}
+ url = reverse('horizon:project:images_and_snapshots:snapshots:create',
+ args=[server.id])
+ res = self.client.post(url, formData)
+ redirect = reverse("horizon:project:instances:index")
+ self.assertRedirectsNoFollow(res, redirect)
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/urls.py b/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/urls.py
new file mode 100644
index 000000000..6fa2ca9f2
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/urls.py
@@ -0,0 +1,30 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import patterns, url
+
+from .views import CreateView
+
+
+urlpatterns = patterns('',
+ url(r'^(?P<instance_id>[^/]+)/create',
+ CreateView.as_view(),
+ name='create')
+)
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/views.py b/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/views.py
new file mode 100644
index 000000000..b23a8a65f
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/snapshots/views.py
@@ -0,0 +1,63 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.
+
+"""
+Views for managing instance snapshots.
+"""
+
+import logging
+
+from django.core.urlresolvers import reverse, reverse_lazy
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+
+from openstack_dashboard import api
+from .forms import CreateSnapshot
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateView(forms.ModalFormView):
+ form_class = CreateSnapshot
+ template_name = 'project/images_and_snapshots/snapshots/create.html'
+ success_url = reverse_lazy("horizon:project:images_and_snapshots:index")
+
+ def get_object(self):
+ if not hasattr(self, "_object"):
+ try:
+ self._object = api.server_get(self.request,
+ self.kwargs["instance_id"])
+ except:
+ redirect = reverse('horizon:project:instances:index')
+ exceptions.handle(self.request,
+ _("Unable to retrieve instance."),
+ redirect=redirect)
+ return self._object
+
+ def get_initial(self):
+ return {"instance_id": self.kwargs["instance_id"]}
+
+ def get_context_data(self, **kwargs):
+ context = super(CreateView, self).get_context_data(**kwargs)
+ context['instance'] = self.get_object()
+ return context
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html
new file mode 100644
index 000000000..f06cfd9f0
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html
@@ -0,0 +1,33 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}create_image_form{% endblock %}
+{% block form_action %}{% url horizon:project:images_and_snapshots:images:create %}{% endblock %}
+
+{% block modal-header %}{% trans "Create An Image" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description:" %}</h3>
+ <p>
+ {% trans "Specify an image to upload to the Image Service." %}
+ </p>
+ <p>
+ {% trans "Currently only images available via an HTTP URL are supported. The image location must be accessible to the Image Service. Compressed image binaries are supported (.zip and .tar.gz.)" %}
+ </p>
+ <p>
+ <strong>{% trans "Please note: " %}</strong>
+ {% trans "The Image Location field MUST be a valid and direct URL to the image binary. URLs that redirect or serve error pages will result in unusable images." %}
+ </p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Image" %}" />
+ <a href="{% url horizon:project:images_and_snapshots:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html
new file mode 100644
index 000000000..1e642eda5
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html
@@ -0,0 +1,68 @@
+{% load i18n sizeformat %}
+
+<h3>{% trans "Image Overview" %}</h3>
+
+<div class="info row-fluid detail">
+ <h4>{% trans "Info" %}</h4>
+ <hr class="header_rule">
+ <dl>
+ <dt>{% trans "Name" %}</dt>
+ <dd>{{ image.name|default:"None" }}</dd>
+ <dt>{% trans "ID" %}</dt>
+ <dd>{{ image.id|default:"None" }}</dd>
+ <dt>{% trans "Status" %}</dt>
+ <dd>{{ image.status|default:"Unknown"|title }}</dd>
+ <dt>{% trans "Public" %}</dt>
+ <dd>{{ image.is_public }}</dd>
+ <dt>{% trans "Checksum" %}</dt>
+ <dd>{{ image.checksum }}</dd>
+ <dt>{% trans "Created" %}</dt>
+ <dd>{{ image.created_at|default:"Unknown" }}</dd>
+ <dt>{% trans "Updated" %}</dt>
+ <dd>{{ image.updated_app|default:"Never updated" }}</dd>
+ </dl>
+</div>
+
+<div class="specs row-fluid detail">
+ <h4>{% trans "Specs" %}</h4>
+ <hr class="header_rule">
+ <dl>
+ <dt>{% trans "Size" %}</dt>
+ <dd>{{ image.size|filesizeformat }}</dd>
+ <dt>{% trans "Container Format" %}</dt>
+ <dd>{{ image.container_format|default:"None"|upper }}</dd>
+ <dt>{% trans "Disk Format" %}</dt>
+ <dd>{{ image.disk_format|default:"None"|upper }}</dd>
+ </dl>
+</div>
+
+<div class="properties row-fluid detail">
+ <h4>{% trans "Custom Properties" %}</h4>
+ <hr class="header_rule">
+ <dl>
+ {% if image.properties.architecture %}
+ <dt>{% trans "Architecture" %}</dt>
+ <dd>{{ image.properties.architecture }}</dd>
+ {% endif %}
+ {% if image.properties.kernel_id %}
+ <dt>{% trans "Kernel ID" %}</dt>
+ <dd>{{ image.properties.kernel_id }}</dd>
+ {% endif %}
+ {% if image.properties.ramdisk_id %}
+ <dt>{% trans "Ramdisk ID" %}</dt>
+ <dd>{{ image.properties.ramdisk_id }}</dd>
+ {% endif %}
+ {% if image.properties.image_state %}
+ <dt>{% trans "Euca2ools state" %}</dt>
+ <dd>{{ image.properties.image_state }}</dd>
+ {% endif %}
+ {% if image.properties.project_id %}
+ <dt>{% trans "Project ID" %}</dt>
+ <dd>{{ image.properties.project_id }}</dd>
+ {% endif %}
+ {% if image.properties.image_type %}
+ <dt>{% trans "Image Type" %}</dt>
+ <dd>{{ image.properties.image_type }}</dd>
+ {% endif %}
+ </dl>
+</div>
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html
new file mode 100644
index 000000000..c94176fd7
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html
@@ -0,0 +1,24 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}update_image_form{% endblock %}
+{% block form_action %}{% url horizon:project:images_and_snapshots:images:update image.id %}{% endblock %}
+
+{% block modal-header %}{% trans "Update Image" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description:" %}</h3>
+ <p>{% trans "From here you can modify different properties of an image." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Update Image" %}" />
+ <a href="{% url horizon:project:images_and_snapshots:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html
new file mode 100644
index 000000000..e8f92f7f2
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Create An Image" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Create An Image") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'project/images_and_snapshots/images/_create.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html
new file mode 100644
index 000000000..17aeb48d9
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html
@@ -0,0 +1,16 @@
+{% extends 'base.html' %}
+{% load i18n %}
+
+{% block title %}{% trans "Image Detail "%}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title="Image Detail" %}
+{% endblock page_header %}
+
+{% block main %}
+<div class="row-fluid">
+ <div class="span12">
+ {{ tab_group.render }}
+ </div>
+</div>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html
new file mode 100644
index 000000000..604898b89
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Update Image" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Update Image") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'project/images_and_snapshots/images/_update.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html
new file mode 100644
index 000000000..4064ac62d
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html
@@ -0,0 +1,19 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Images &amp; Snapshots" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Images &amp; Snapshots") %}
+{% endblock page_header %}
+
+{% block main %}
+ <div class="images">
+ {{ images_table.render }}
+ </div>
+ <div class="snapshots">
+ {{ snapshots_table.render }}
+ </div>
+ <div class="volume_snapshots">
+ {{ volume_snapshots_table.render }}
+ </div>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html
new file mode 100644
index 000000000..d2bf9b957
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}create_snapshot_form{% endblock %}
+{% block form_action %}{% url horizon:project:images_and_snapshots:snapshots:create instance.id %}{% endblock %}
+
+{% block modal_id %}create_snapshot_modal{% endblock %}
+{% block modal-header %}{% trans "Create Snapshot" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description:" %}</h3>
+ <p>{% trans "Snapshots preserve the disk state of a running instance." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Snapshot" %}" />
+ <a href="{% url horizon:project:images_and_snapshots:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html
new file mode 100644
index 000000000..484bd0e3a
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html
@@ -0,0 +1,42 @@
+{% load i18n sizeformat parse_date %}
+{% load url from future %}
+
+<h3>{{snapshot.display_name }}</h3>
+
+<div class="info row-fluid detail">
+ <h4>{% trans "Info" %}</h4>
+ <hr class="header_rule">
+ <dl>
+ <dt>{% trans "Name" %}</dt>
+ <dd>{{ snapshot.display_name }}</dd>
+ <dt>{% trans "ID" %}</dt>
+ <dd>{{ snapshot.id }}</dd>
+ {% if snapshot.display_description %}
+ <dt>{% trans "Description" %}</dt>
+ <dd>{{ snapshot.display_description }}</dd>
+ {% endif %}
+ <dt>{% trans "Status" %}</dt>
+ <dd>{{ snapshot.status|capfirst }}</dd>
+ <dt>{% trans "Volume" %}</dt>
+ <dd>
+ <a href="{% url 'horizon:project:volumes:detail' snapshot.volume_id %}">
+ {% if volume.display_name %}
+ {{ volume.display_name }}
+ {% else %}
+ {{ snapshot.volume_id }}
+ {% endif %}
+ </a>
+ </dd>
+ </dl>
+</div>
+
+<div class="specs row-fluid detail">
+ <h4>{% trans "Specs" %}</h4>
+ <hr class="header_rule">
+ <dl>
+ <dt>{% trans "Size" %}</dt>
+ <dd>{{ snapshot.size }} {% trans "GB" %}</dd>
+ <dt>{% trans "Created" %}</dt>
+ <dd>{{ snapshot.created_at|parse_date }}</dd>
+ </dl>
+</div>
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html
new file mode 100644
index 000000000..51c7d4b5c
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Create Snapshot" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Create a Snapshot") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'project/images_and_snapshots/snapshots/_create.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html
new file mode 100644
index 000000000..72d8dc668
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html
@@ -0,0 +1,15 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Volume Snapshot Details" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Volume Snapshot Detail") %}
+{% endblock page_header %}
+
+{% block main %}
+<div class="row-fluid">
+ <div class="span12">
+ {{ tab_group.render }}
+ </div>
+</div>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/tests.py b/openstack_dashboard/dashboards/project/images_and_snapshots/tests.py
new file mode 100644
index 000000000..52ee152b8
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/tests.py
@@ -0,0 +1,170 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+# Copyright 2012 OpenStack LLC
+#
+# 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 import http
+from django.core.urlresolvers import reverse
+
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+INDEX_URL = reverse('horizon:project:images_and_snapshots:index')
+
+
+class ImagesAndSnapshotsTests(test.TestCase):
+ @test.create_stubs({api: ('image_list_detailed', 'snapshot_list_detailed',
+ 'volume_snapshot_list', 'volume_get',)})
+ def test_index(self):
+ images = self.images.list()
+ snapshots = self.snapshots.list()
+ volumes = self.volumes.list()
+
+ for volume in volumes:
+ volume.volume_id = volume.id
+ for volume in volumes:
+ api.volume_get(IsA(http.HttpRequest), volume.volume_id) \
+ .AndReturn(volume)
+ for volume in volumes:
+ api.volume_get(IsA(http.HttpRequest), volume.volume_id) \
+ .AndReturn(volume)
+ api.volume_get(IsA(http.HttpRequest), volume.volume_id)
+
+ api.volume_snapshot_list(IsA(http.HttpRequest)) \
+ .AndReturn(volumes)
+ api.image_list_detailed(IsA(http.HttpRequest),
+ marker=None).AndReturn([images, False])
+ api.snapshot_list_detailed(IsA(http.HttpRequest),
+ marker=None).AndReturn([snapshots, False])
+ self.mox.ReplayAll()
+
+ res = self.client.get(INDEX_URL)
+ self.assertTemplateUsed(res, 'project/images_and_snapshots/index.html')
+ self.assertIn('images_table', res.context)
+ images = res.context['images_table'].data
+ filter_func = lambda im: im.container_format not in ['aki', 'ari']
+ filtered_images = filter(filter_func, images)
+ self.assertItemsEqual(images, filtered_images)
+
+ @test.create_stubs({api: ('image_list_detailed', 'snapshot_list_detailed',
+ 'volume_snapshot_list', 'volume_get',)})
+ def test_index_no_images(self):
+ volumes = self.volumes.list()
+
+ for volume in volumes:
+ volume.volume_id = volume.id
+ for volume in volumes:
+ api.volume_get(IsA(http.HttpRequest), volume.volume_id) \
+ .AndReturn(volume)
+ for volume in volumes:
+ api.volume_get(IsA(http.HttpRequest), volume.volume_id) \
+ .AndReturn(volume)
+ api.volume_get(IsA(http.HttpRequest), volume.volume_id)
+
+ api.volume_snapshot_list(IsA(http.HttpRequest)) \
+ .AndReturn(volumes)
+ api.image_list_detailed(IsA(http.HttpRequest),
+ marker=None).AndReturn([(), False])
+ api.snapshot_list_detailed(IsA(http.HttpRequest), marker=None) \
+ .AndReturn([self.snapshots.list(), False])
+ self.mox.ReplayAll()
+
+ res = self.client.get(INDEX_URL)
+ self.assertTemplateUsed(res, 'project/images_and_snapshots/index.html')
+
+ @test.create_stubs({api: ('image_list_detailed', 'snapshot_list_detailed',
+ 'volume_snapshot_list', 'volume_get',)})
+ def test_index_error(self):
+ volumes = self.volumes.list()
+
+ for volume in volumes:
+ volume.volume_id = volume.id
+ for volume in volumes:
+ api.volume_get(IsA(http.HttpRequest), volume.volume_id) \
+ .AndReturn(volume)
+ for volume in volumes:
+ api.volume_get(IsA(http.HttpRequest), volume.volume_id) \
+ .AndReturn(volume)
+ api.volume_get(IsA(http.HttpRequest), volume.volume_id)
+
+ api.volume_snapshot_list(IsA(http.HttpRequest)) \
+ .AndReturn(volumes)
+ api.image_list_detailed(IsA(http.HttpRequest),
+ marker=None).AndRaise(self.exceptions.glance)
+ api.snapshot_list_detailed(IsA(http.HttpRequest), marker=None) \
+ .AndReturn([self.snapshots.list(), False])
+ self.mox.ReplayAll()
+
+ res = self.client.get(INDEX_URL)
+ self.assertTemplateUsed(res, 'project/images_and_snapshots/index.html')
+
+ @test.create_stubs({api: ('image_list_detailed', 'snapshot_list_detailed',
+ 'volume_snapshot_list', 'volume_get',)})
+ def test_queued_snapshot_actions(self):
+ images = self.images.list()
+ snapshots = self.snapshots.list()
+ volumes = self.volumes.list()
+
+ for volume in volumes:
+ volume.volume_id = volume.id
+ for volume in volumes:
+ api.volume_get(IsA(http.HttpRequest), volume.volume_id) \
+ .AndReturn(volume)
+ for volume in volumes:
+ api.volume_get(IsA(http.HttpRequest), volume.volume_id) \
+ .AndReturn(volume)
+ api.volume_get(IsA(http.HttpRequest), volume.volume_id)
+
+ api.volume_snapshot_list(IsA(http.HttpRequest)) \
+ .AndReturn(volumes)
+ api.image_list_detailed(IsA(http.HttpRequest),
+ marker=None).AndReturn([images, False])
+ api.snapshot_list_detailed(IsA(http.HttpRequest), marker=None) \
+ .AndReturn([snapshots, False])
+ self.mox.ReplayAll()
+
+ res = self.client.get(INDEX_URL)
+ self.assertTemplateUsed(res, 'project/images_and_snapshots/index.html')
+ self.assertIn('snapshots_table', res.context)
+ snaps = res.context['snapshots_table']
+ self.assertEqual(len(snaps.get_rows()), 3)
+
+ row_actions = snaps.get_row_actions(snaps.data[0])
+
+ # first instance - status active, owned
+ self.assertEqual(len(row_actions), 3)
+ self.assertEqual(row_actions[0].verbose_name, u"Launch")
+ self.assertEqual(row_actions[1].verbose_name, u"Edit")
+ self.assertEqual(row_actions[2].verbose_name, u"Delete Snapshot")
+
+ row_actions = snaps.get_row_actions(snaps.data[1])
+
+ # second instance - status active, not owned
+ self.assertEqual(len(row_actions), 1)
+ self.assertEqual(row_actions[0].verbose_name, u"Launch")
+
+ row_actions = snaps.get_row_actions(snaps.data[2])
+ # third instance - status queued, only delete is available
+ self.assertEqual(len(row_actions), 1)
+ self.assertEqual(unicode(row_actions[0].verbose_name),
+ u"Delete Snapshot")
+ self.assertEqual(str(row_actions[0]), "<DeleteSnapshot: delete>")
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/urls.py b/openstack_dashboard/dashboards/project/images_and_snapshots/urls.py
new file mode 100644
index 000000000..d763deace
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/urls.py
@@ -0,0 +1,35 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import *
+
+from .images import urls as image_urls
+from .snapshots import urls as snapshot_urls
+from .views import IndexView, DetailView
+
+
+urlpatterns = patterns('',
+ url(r'^$', IndexView.as_view(), name='index'),
+ url(r'', include(image_urls, namespace='images')),
+ url(r'', include(snapshot_urls, namespace='snapshots')),
+ url(r'^snapshots/(?P<snapshot_id>[^/]+)/$',
+ DetailView.as_view(),
+ name='detail'),
+)
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/views.py b/openstack_dashboard/dashboards/project/images_and_snapshots/views.py
new file mode 100644
index 000000000..8792ada35
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/views.py
@@ -0,0 +1,89 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+# Copyright 2012 OpenStack LLC
+#
+# 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.
+
+"""
+Views for managing Images and Snapshots.
+"""
+
+import logging
+
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tables
+from horizon import tabs
+
+from openstack_dashboard import api
+from .images.tables import ImagesTable
+from .snapshots.tables import SnapshotsTable
+from .volume_snapshots.tables import VolumeSnapshotsTable
+from .volume_snapshots.tabs import SnapshotDetailTabs
+
+LOG = logging.getLogger(__name__)
+
+
+class IndexView(tables.MultiTableView):
+ table_classes = (ImagesTable, SnapshotsTable, VolumeSnapshotsTable)
+ template_name = 'project/images_and_snapshots/index.html'
+
+ def has_more_data(self, table):
+ return getattr(self, "_more_%s" % table.name, False)
+
+ def get_images_data(self):
+ marker = self.request.GET.get(ImagesTable._meta.pagination_param, None)
+ try:
+ # FIXME(gabriel): The paging is going to be strange here due to
+ # our filtering after the fact.
+ (all_images,
+ self._more_images) = api.image_list_detailed(self.request,
+ marker=marker)
+ images = [im for im in all_images
+ if im.container_format not in ['aki', 'ari'] and
+ im.properties.get("image_type", '') != "snapshot"]
+ except:
+ images = []
+ exceptions.handle(self.request, _("Unable to retrieve images."))
+ return images
+
+ def get_snapshots_data(self):
+ req = self.request
+ marker = req.GET.get(SnapshotsTable._meta.pagination_param, None)
+ try:
+ snaps, self._more_snapshots = api.snapshot_list_detailed(req,
+ marker=marker)
+ except:
+ snaps = []
+ exceptions.handle(req, _("Unable to retrieve snapshots."))
+ return snaps
+
+ def get_volume_snapshots_data(self):
+ try:
+ snapshots = api.volume_snapshot_list(self.request)
+ except:
+ snapshots = []
+ exceptions.handle(self.request, _("Unable to retrieve "
+ "volume snapshots."))
+ return snapshots
+
+
+class DetailView(tabs.TabView):
+ tab_group_class = SnapshotDetailTabs
+ template_name = 'project/images_and_snapshots/snapshots/detail.html'
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/volume_snapshots/__init__.py b/openstack_dashboard/dashboards/project/images_and_snapshots/volume_snapshots/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/volume_snapshots/__init__.py
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/volume_snapshots/tables.py b/openstack_dashboard/dashboards/project/images_and_snapshots/volume_snapshots/tables.py
new file mode 100644
index 000000000..1ef6e02d3
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/volume_snapshots/tables.py
@@ -0,0 +1,89 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.utils import safestring
+from django.utils.http import urlencode
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import tables
+
+from openstack_dashboard import api
+from ...volumes import tables as volume_tables
+
+
+LOG = logging.getLogger(__name__)
+
+
+class DeleteVolumeSnapshot(tables.DeleteAction):
+ data_type_singular = _("Volume Snapshot")
+ data_type_plural = _("Volume Snapshots")
+
+ def delete(self, request, obj_id):
+ api.volume_snapshot_delete(request, obj_id)
+
+
+class CreateVolumeFromSnapshot(tables.LinkAction):
+ name = "create_from_snapshot"
+ verbose_name = _("Create Volume")
+ url = "horizon:project:volumes:create"
+ classes = ("ajax-modal", "btn-camera")
+
+ def get_link_url(self, datum):
+ base_url = reverse(self.url)
+ params = urlencode({"snapshot_id": self.table.get_object_id(datum)})
+ return "?".join([base_url, params])
+
+ def allowed(self, request, volume=None):
+ return volume.status == "available" if volume else False
+
+
+class UpdateRow(tables.Row):
+ ajax = True
+
+ def get_data(self, request, snapshot_id):
+ snapshot = api.nova.volume_snapshot_get(request, snapshot_id)
+ return snapshot
+
+
+class SnapshotVolumeNameColumn(tables.Column):
+ def get_raw_data(self, snapshot):
+ request = self.table.request
+ volume_name = api.volume_get(request, snapshot.volume_id).display_name
+ return safestring.mark_safe(volume_name)
+
+ def get_link_url(self, snapshot):
+ volume_id = api.volume_get(self.table.request, snapshot.volume_id).id
+ return reverse(self.link, args=(volume_id,))
+
+
+class VolumeSnapshotsTable(volume_tables.VolumesTableBase):
+ name = tables.Column("display_name",
+ verbose_name=_("Name"),
+ link="horizon:project:images_and_snapshots:detail")
+ volume_name = SnapshotVolumeNameColumn("display_name",
+ verbose_name=_("Volume Name"),
+ link="horizon:project:volumes:detail")
+
+ class Meta:
+ name = "volume_snapshots"
+ verbose_name = _("Volume Snapshots")
+ table_actions = (DeleteVolumeSnapshot,)
+ row_actions = (CreateVolumeFromSnapshot, DeleteVolumeSnapshot)
+ row_class = UpdateRow
+ status_columns = ("status",)
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/volume_snapshots/tabs.py b/openstack_dashboard/dashboards/project/images_and_snapshots/volume_snapshots/tabs.py
new file mode 100644
index 000000000..cd4c2222e
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/volume_snapshots/tabs.py
@@ -0,0 +1,49 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tabs
+
+from openstack_dashboard import api
+
+
+class OverviewTab(tabs.Tab):
+ name = _("Overview")
+ slug = "overview"
+ template_name = ("project/images_and_snapshots/snapshots/"
+ "_detail_overview.html")
+
+ def get_context_data(self, request):
+ snapshot_id = self.tab_group.kwargs['snapshot_id']
+ try:
+ snapshot = api.nova.volume_snapshot_get(request, snapshot_id)
+ volume = api.nova.volume_get(request, snapshot.volume_id)
+ volume.display_name = None
+ except:
+ redirect = reverse('horizon:project:images_and_snapshots:index')
+ exceptions.handle(self.request,
+ _('Unable to retrieve snapshot details.'),
+ redirect=redirect)
+ return {'snapshot': snapshot,
+ 'volume': volume}
+
+
+class SnapshotDetailTabs(tabs.TabGroup):
+ slug = "snapshot_details"
+ tabs = (OverviewTab,)
diff --git a/openstack_dashboard/dashboards/project/images_and_snapshots/volume_snapshots/tests.py b/openstack_dashboard/dashboards/project/images_and_snapshots/volume_snapshots/tests.py
new file mode 100644
index 000000000..1cdba5b29
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/images_and_snapshots/volume_snapshots/tests.py
@@ -0,0 +1,61 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2011 Nebula, Inc.
+#
+# 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 import http
+from django.core.urlresolvers import reverse
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+INDEX_URL = reverse('horizon:project:images_and_snapshots:index')
+
+
+class VolumeSnapshotsViewTests(test.TestCase):
+ def test_create_snapshot_get(self):
+ volume = self.volumes.first()
+ url = reverse('horizon:project:volumes:create_snapshot',
+ args=[volume.id])
+ res = self.client.get(url)
+
+ self.assertTemplateUsed(res, 'project/volumes/create_snapshot.html')
+
+ def test_create_snapshot_post(self):
+ volume = self.volumes.first()
+ snapshot = self.volume_snapshots.first()
+
+ self.mox.StubOutWithMock(api, 'volume_snapshot_create')
+ api.volume_snapshot_create(IsA(http.HttpRequest),
+ volume.id,
+ snapshot.display_name,
+ snapshot.display_description) \
+ .AndReturn(snapshot)
+ self.mox.ReplayAll()
+
+ formData = {'method': 'CreateSnapshotForm',
+ 'tenant_id': self.tenant.id,
+ 'volume_id': volume.id,
+ 'name': snapshot.display_name,
+ 'description': snapshot.display_description}
+ url = reverse('horizon:project:volumes:create_snapshot',
+ args=[volume.id])
+ res = self.client.post(url, formData)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
diff --git a/openstack_dashboard/dashboards/project/instances/__init__.py b/openstack_dashboard/dashboards/project/instances/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/__init__.py
diff --git a/openstack_dashboard/dashboards/project/instances/forms.py b/openstack_dashboard/dashboards/project/instances/forms.py
new file mode 100644
index 000000000..569053d22
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/forms.py
@@ -0,0 +1,51 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from openstack_dashboard import api
+
+from horizon import exceptions
+from horizon import forms
+from horizon import messages
+
+
+LOG = logging.getLogger(__name__)
+
+
+class UpdateInstance(forms.SelfHandlingForm):
+ tenant_id = forms.CharField(widget=forms.HiddenInput)
+ instance = forms.CharField(widget=forms.HiddenInput)
+ name = forms.CharField(required=True)
+
+ def handle(self, request, data):
+ try:
+ server = api.server_update(request, data['instance'], data['name'])
+ messages.success(request,
+ _('Instance "%s" updated.') % data['name'])
+ return server
+ except:
+ redirect = reverse("horizon:project:instances:index")
+ exceptions.handle(request,
+ _('Unable to update instance.'),
+ redirect=redirect)
diff --git a/openstack_dashboard/dashboards/project/instances/panel.py b/openstack_dashboard/dashboards/project/instances/panel.py
new file mode 100644
index 000000000..c204973ed
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/panel.py
@@ -0,0 +1,29 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 Instances(horizon.Panel):
+ name = _("Instances")
+ slug = 'instances'
+
+
+dashboard.Project.register(Instances)
diff --git a/openstack_dashboard/dashboards/project/instances/tables.py b/openstack_dashboard/dashboards/project/instances/tables.py
new file mode 100644
index 000000000..dc3939f10
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/tables.py
@@ -0,0 +1,319 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django import template
+from django.core import urlresolvers
+from django.template.defaultfilters import title
+from django.utils.http import urlencode
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import tables
+from horizon.templatetags import sizeformat
+from horizon.utils.filters import replace_underscores
+
+from openstack_dashboard import api
+from openstack_dashboard.dashboards.project.access_and_security \
+ .floating_ips.workflows import IPAssociationWorkflow
+from .tabs import InstanceDetailTabs, LogTab, VNCTab
+
+
+LOG = logging.getLogger(__name__)
+
+ACTIVE_STATES = ("ACTIVE",)
+
+POWER_STATES = {
+ 0: "NO STATE",
+ 1: "RUNNING",
+ 2: "BLOCKED",
+ 3: "PAUSED",
+ 4: "SHUTDOWN",
+ 5: "SHUTOFF",
+ 6: "CRASHED",
+ 7: "SUSPENDED",
+ 8: "FAILED",
+ 9: "BUILDING",
+}
+
+PAUSE = 0
+UNPAUSE = 1
+SUSPEND = 0
+RESUME = 1
+
+
+def _is_deleting(instance):
+ task_state = getattr(instance, "OS-EXT-STS:task_state", None)
+ if not task_state:
+ return False
+ return task_state.lower() == "deleting"
+
+
+class TerminateInstance(tables.BatchAction):
+ name = "terminate"
+ action_present = _("Terminate")
+ action_past = _("Scheduled termination of")
+ data_type_singular = _("Instance")
+ data_type_plural = _("Instances")
+ classes = ('btn-danger', 'btn-terminate')
+
+ def allowed(self, request, instance=None):
+ if instance:
+ # FIXME(gabriel): This is true in Essex, but in FOLSOM an instance
+ # can be terminated in any state. We should improve this error
+ # handling when LP bug 1037241 is implemented.
+ return instance.status not in ("PAUSED", "SUSPENDED")
+ return True
+
+ def action(self, request, obj_id):
+ api.server_delete(request, obj_id)
+
+
+class RebootInstance(tables.BatchAction):
+ name = "reboot"
+ action_present = _("Reboot")
+ action_past = _("Rebooted")
+ data_type_singular = _("Instance")
+ data_type_plural = _("Instances")
+ classes = ('btn-danger', 'btn-reboot')
+
+ def allowed(self, request, instance=None):
+ return ((instance.status in ACTIVE_STATES
+ or instance.status == 'SHUTOFF')
+ and not _is_deleting(instance))
+
+ def action(self, request, obj_id):
+ api.server_reboot(request, obj_id)
+
+
+class TogglePause(tables.BatchAction):
+ name = "pause"
+ action_present = (_("Pause"), _("Unpause"))
+ action_past = (_("Paused"), _("Unpaused"))
+ data_type_singular = _("Instance")
+ data_type_plural = _("Instances")
+ classes = ("btn-pause",)
+
+ def allowed(self, request, instance=None):
+ self.paused = False
+ if not instance:
+ return self.paused
+ self.paused = instance.status == "PAUSED"
+ if self.paused:
+ self.current_present_action = UNPAUSE
+ else:
+ self.current_present_action = PAUSE
+ return ((instance.status in ACTIVE_STATES or self.paused)
+ and not _is_deleting(instance))
+
+ def action(self, request, obj_id):
+ if self.paused:
+ api.server_unpause(request, obj_id)
+ self.current_past_action = UNPAUSE
+ else:
+ api.server_pause(request, obj_id)
+ self.current_past_action = PAUSE
+
+
+class ToggleSuspend(tables.BatchAction):
+ name = "suspend"
+ action_present = (_("Suspend"), _("Resume"))
+ action_past = (_("Suspended"), _("Resumed"))
+ data_type_singular = _("Instance")
+ data_type_plural = _("Instances")
+ classes = ("btn-suspend",)
+
+ def allowed(self, request, instance=None):
+ self.suspended = False
+ if not instance:
+ self.suspended
+ self.suspended = instance.status == "SUSPENDED"
+ if self.suspended:
+ self.current_present_action = RESUME
+ else:
+ self.current_present_action = SUSPEND
+ return ((instance.status in ACTIVE_STATES or self.suspended)
+ and not _is_deleting(instance))
+
+ def action(self, request, obj_id):
+ if self.suspended:
+ api.server_resume(request, obj_id)
+ self.current_past_action = RESUME
+ else:
+ api.server_suspend(request, obj_id)
+ self.current_past_action = SUSPEND
+
+
+class LaunchLink(tables.LinkAction):
+ name = "launch"
+ verbose_name = _("Launch Instance")
+ url = "horizon:project:instances:launch"
+ classes = ("btn-launch", "ajax-modal")
+
+
+class EditInstance(tables.LinkAction):
+ name = "edit"
+ verbose_name = _("Edit Instance")
+ url = "horizon:project:instances:update"
+ classes = ("ajax-modal", "btn-edit")
+
+ def allowed(self, request, instance):
+ return not _is_deleting(instance)
+
+
+class CreateSnapshot(tables.LinkAction):
+ name = "snapshot"
+ verbose_name = _("Create Snapshot")
+ url = "horizon:project:images_and_snapshots:snapshots:create"
+ classes = ("ajax-modal", "btn-camera")
+
+ def allowed(self, request, instance=None):
+ return instance.status in ACTIVE_STATES and not _is_deleting(instance)
+
+
+class ConsoleLink(tables.LinkAction):
+ name = "console"
+ verbose_name = _("VNC Console")
+ url = "horizon:project:instances:detail"
+ classes = ("btn-console",)
+
+ def allowed(self, request, instance=None):
+ return instance.status in ACTIVE_STATES and not _is_deleting(instance)
+
+ def get_link_url(self, datum):
+ base_url = super(ConsoleLink, self).get_link_url(datum)
+ tab_query_string = VNCTab(InstanceDetailTabs).get_query_string()
+ return "?".join([base_url, tab_query_string])
+
+
+class LogLink(tables.LinkAction):
+ name = "log"
+ verbose_name = _("View Log")
+ url = "horizon:project:instances:detail"
+ classes = ("btn-log",)
+
+ def allowed(self, request, instance=None):
+ return instance.status in ACTIVE_STATES and not _is_deleting(instance)
+
+ def get_link_url(self, datum):
+ base_url = super(LogLink, self).get_link_url(datum)
+ tab_query_string = LogTab(InstanceDetailTabs).get_query_string()
+ return "?".join([base_url, tab_query_string])
+
+
+class AssociateIP(tables.LinkAction):
+ name = "associate"
+ verbose_name = _("Associate Floating IP")
+ url = "horizon:project:access_and_security:floating_ips:associate"
+ classes = ("ajax-modal", "btn-associate")
+
+ def allowed(self, request, instance):
+ return not _is_deleting(instance)
+
+ def get_link_url(self, datum):
+ base_url = urlresolvers.reverse(self.url)
+ next = urlresolvers.reverse("horizon:project:instances:index")
+ params = {"instance_id": self.table.get_object_id(datum),
+ IPAssociationWorkflow.redirect_param_name: next}
+ params = urlencode(params)
+ return "?".join([base_url, params])
+
+
+class UpdateRow(tables.Row):
+ ajax = True
+
+ def get_data(self, request, instance_id):
+ instance = api.server_get(request, instance_id)
+ instance.full_flavor = api.flavor_get(request, instance.flavor["id"])
+ return instance
+
+
+def get_ips(instance):
+ template_name = 'project/instances/_instance_ips.html'
+ context = {"instance": instance}
+ return template.loader.render_to_string(template_name, context)
+
+
+def get_size(instance):
+ if hasattr(instance, "full_flavor"):
+ size_string = _("%(name)s | %(RAM)s RAM | %(VCPU)s VCPU "
+ "| %(disk)s Disk")
+ vals = {'name': instance.full_flavor.name,
+ 'RAM': sizeformat.mbformat(instance.full_flavor.ram),
+ 'VCPU': instance.full_flavor.vcpus,
+ 'disk': sizeformat.diskgbformat(instance.full_flavor.disk)}
+ return size_string % vals
+ return _("Not available")
+
+
+def get_keyname(instance):
+ if hasattr(instance, "key_name"):
+ keyname = instance.key_name
+ return keyname
+ return _("Not available")
+
+
+def get_power_state(instance):
+ return POWER_STATES.get(getattr(instance, "OS-EXT-STS:power_state", 0), '')
+
+
+class InstancesTable(tables.DataTable):
+ TASK_STATUS_CHOICES = (
+ (None, True),
+ ("none", True)
+ )
+ STATUS_CHOICES = (
+ ("active", True),
+ ("shutoff", True),
+ ("suspended", True),
+ ("paused", True),
+ ("error", False),
+ )
+ TASK_DISPLAY_CHOICES = (
+ ("image_snapshot", "Snapshotting"),
+ )
+ name = tables.Column("name",
+ link=("horizon:project:instances:detail"),
+ verbose_name=_("Instance Name"))
+ ip = tables.Column(get_ips, verbose_name=_("IP Address"))
+ size = tables.Column(get_size,
+ verbose_name=_("Size"),
+ attrs={'data-type': 'size'})
+ keypair = tables.Column(get_keyname, verbose_name=_("Keypair"))
+ status = tables.Column("status",
+ filters=(title, replace_underscores),
+ verbose_name=_("Status"),
+ status=True,
+ status_choices=STATUS_CHOICES)
+ task = tables.Column("OS-EXT-STS:task_state",
+ verbose_name=_("Task"),
+ filters=(title, replace_underscores),
+ status=True,
+ status_choices=TASK_STATUS_CHOICES,
+ display_choices=TASK_DISPLAY_CHOICES)
+ state = tables.Column(get_power_state,
+ filters=(title, replace_underscores),
+ verbose_name=_("Power State"))
+
+ class Meta:
+ name = "instances"
+ verbose_name = _("Instances")
+ status_columns = ["status", "task"]
+ row_class = UpdateRow
+ table_actions = (LaunchLink, TerminateInstance)
+ row_actions = (CreateSnapshot, AssociateIP, EditInstance, ConsoleLink,
+ LogLink, TogglePause, ToggleSuspend, RebootInstance,
+ TerminateInstance)
diff --git a/openstack_dashboard/dashboards/project/instances/tabs.py b/openstack_dashboard/dashboards/project/instances/tabs.py
new file mode 100644
index 000000000..87dbb2818
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/tabs.py
@@ -0,0 +1,78 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 _
+
+from horizon import exceptions
+from horizon import tabs
+
+from openstack_dashboard import api
+
+
+class OverviewTab(tabs.Tab):
+ name = _("Overview")
+ slug = "overview"
+ template_name = ("project/instances/"
+ "_detail_overview.html")
+
+ def get_context_data(self, request):
+ return {"instance": self.tab_group.kwargs['instance']}
+
+
+class LogTab(tabs.Tab):
+ name = _("Log")
+ slug = "log"
+ template_name = "project/instances/_detail_log.html"
+ preload = False
+
+ def get_context_data(self, request):
+ instance = self.tab_group.kwargs['instance']
+ try:
+ data = api.server_console_output(request,
+ instance.id,
+ tail_length=35)
+ except:
+ data = _('Unable to get log for instance "%s".') % instance.id
+ exceptions.handle(request, ignore=True)
+ return {"instance": instance,
+ "console_log": data}
+
+
+class VNCTab(tabs.Tab):
+ name = _("VNC")
+ slug = "vnc"
+ template_name = "project/instances/_detail_vnc.html"
+ preload = False
+
+ def get_context_data(self, request):
+ instance = self.tab_group.kwargs['instance']
+ try:
+ console = api.nova.server_vnc_console(request, instance.id)
+ vnc_url = "%s&title=%s(%s)" % (console.url,
+ getattr(instance, "name", ""),
+ instance.id)
+ except:
+ vnc_url = None
+ exceptions.handle(request,
+ _('Unable to get VNC console for '
+ 'instance "%s".') % instance.id)
+ return {'vnc_url': vnc_url, 'instance_id': instance.id}
+
+
+class InstanceDetailTabs(tabs.TabGroup):
+ slug = "instance_details"
+ tabs = (OverviewTab, LogTab, VNCTab)
+ sticky = True
diff --git a/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_log.html b/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_log.html
new file mode 100644
index 000000000..79ad9098c
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_log.html
@@ -0,0 +1,17 @@
+{% load i18n %}
+
+<div class="clearfix">
+ <h3 class="pull-left">{% trans "Instance Console Log" %}</h3>
+
+ <form id="tail_length" action="{% url horizon:project:instances:console instance.id %}" class="form-inline pull-right">
+ <label for="tail_length_select">{% trans "Log Length" %}</label>
+ <input class="span1" type="text" name="length" value="35" />
+ <button class="btn btn-small btn-primary" type="submit">{% trans "Go" %}</button>
+ {% url horizon:project:instances:console instance.id as console_url %}
+ <a class="btn btn-small" target="_blank" href="{{ console_url }}">{% trans "View Full Log" %}</a>
+ </form>
+</div>
+
+<pre class="logs">
+ {{ console_log }}
+</pre>
diff --git a/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_overview.html b/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_overview.html
new file mode 100644
index 000000000..c71f87d1a
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_overview.html
@@ -0,0 +1,98 @@
+{% load i18n sizeformat %}
+
+<h3>{% trans "Instance Overview" %}</h3>
+
+<div class="status row-fluid detail">
+ <h4>{% trans "Info" %}</h4>
+ <hr class="header_rule">
+ <dl>
+ <dt>{% trans "Name" %}</dt>
+ <dd>{{ instance.name }}</dd>
+ <dt>{% trans "ID" %}</dt>
+ <dd>{{ instance.id }}</dd>
+ <dt>{% trans "Status" %}</dt>
+ <dd>{{ instance.status|title }}</dd>
+ </dl>
+</div>
+
+<div class="specs row-fluid detail">
+ <h4>{% trans "Specs" %}</h4>
+ <hr class="header_rule">
+ <dl>
+ <dt>{% trans "Flavor" %}</dt>
+ <dd>{{ instance.full_flavor.name }}</dd>
+ <dt>{% trans "RAM" %}</dt>
+ <dd>{{ instance.full_flavor.ram|mbformat }}</dd>
+ <dt>{% trans "VCPUs" %}</dt>
+ <dd>{{ instance.full_flavor.vcpus }} {% trans "VCPU" %}</dd>
+ <dt>{% trans "Disk" %}</dt>
+ <dd>{{ instance.full_flavor.disk }}{% trans "GB" %}</dd>
+ </dl>
+</div>
+
+<div class="addresses row-fluid detail">
+ <h4>{% trans "IP Addresses" %}</h4>
+ <hr class="header_rule">
+ <dl>
+ {% for network, ip_list in instance.addresses.items %}
+ <dt>{{ network|title }}</dt>
+ <dd>
+ {% for ip in ip_list %}
+ {% if not forloop.last %}{{ ip.addr}},&nbsp;{% else %}{{ip.addr}}{% endif %}
+ {% endfor %}
+ </dd>
+ {% endfor %}
+ </dl>
+</div>
+
+<div class="security_groups row-fluid detail">
+ <h4>{% trans "Security Groups" %}</h4>
+ <hr class="header_rule">
+ <dl>
+ {% for group in instance.security_groups %}
+ <dt>{{ group.name }}</dt>
+ <dd>
+ <ul>
+ {% for rule in group.rules %}
+ <li>{{ rule }}</li>
+ {% empty %}
+ <li><em>{% trans "No rules defined." %}</em></li>
+ {% endfor %}
+ </ul>
+ </dd>
+ {% endfor %}
+ </dl>
+</div>
+
+<div class="meta row-fluid detail">
+ <h4>{% trans "Meta" %}</h4>
+ <hr class="header_rule">
+ <dl>
+ <dt>{% trans "Key Name" %}</dt>
+ <dd>{{ instance.key_name|default:"<em>None</em>" }}</dd>
+ {% url horizon:project:images_and_snapshots:images:detail instance.image.id as image_url %}
+ <dt>{% trans "Image Name" %}</dt>
+ <dd><a href="{{ image_url }}">{{ instance.image_name }}</a></dd>
+ {% for key, value in instance.metadata.items %}
+ <dt>{{ key|force_escape }}</dt>
+ <dd>{{ value|force_escape|default:"<em>N/A</em>" }}</dd>
+ {% endfor%}
+ </dl>
+</div>
+
+<div class="volumes row-fluid detail">
+ <h4>{% trans "Volumes Attached" %}</h4>
+ <hr class="header_rule">
+ <dl>
+ {% for volume in instance.volumes %}
+ <dt>{% trans "Attached To" %}</dt>
+ <dd>
+ <a href="{% url horizon:project:volumes:detail volume.volumeId %}">{{ volume.name }}</a><span> {% trans "on" %} {{ volume.device }}</span>
+ </dd>
+ {% empty %}
+ <dt>{% trans "Volume" %}</dt>
+ <dd><em>{% trans "No volumes attached." %}</em></dd>
+ {% endfor %}
+ </dl>
+ </dl>
+</div>
diff --git a/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_vnc.html b/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_vnc.html
new file mode 100644
index 000000000..02abba7dc
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/templates/instances/_detail_vnc.html
@@ -0,0 +1,10 @@
+{% load i18n %}
+
+<h3>{% trans "Instance VNC Console" %}</h3>
+{% if vnc_url %}
+<p class='alert alert-info'>{% blocktrans %}If VNC console is not responding to keyboard input: click the grey status bar below.{% endblocktrans %} <a href="{{ vnc_url }}">{% trans "Click here to show only VNC" %}</a></p>
+<iframe src="{{ vnc_url }}" width="728" height="436"></iframe>
+{% else %}
+<p class='alert alert-error'>{% blocktrans %}VNC console is currently unavailabe. Please try again later.{% endblocktrans %}
+<a class='btn btn-mini' href="{% url horizon:project:instances:detail instance_id %}">{% trans "Reload" %}</a></p>
+{% endif %} \ No newline at end of file
diff --git a/openstack_dashboard/dashboards/project/instances/templates/instances/_instance_ips.html b/openstack_dashboard/dashboards/project/instances/templates/instances/_instance_ips.html
new file mode 100644
index 000000000..72ed59fe6
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/templates/instances/_instance_ips.html
@@ -0,0 +1,10 @@
+{% for ip_group, addresses in instance.addresses.items %}
+ {% if instance.addresses.items|length > 1 %}
+ <h4>{{ ip_group }}</h4>
+ {% endif %}
+ <ul>
+ {% for address in addresses %}
+ <li>{{ address.addr }}</li>
+ {% endfor %}
+ </ul>
+{% endfor %}
diff --git a/openstack_dashboard/dashboards/project/instances/templates/instances/_launch_customize_help.html b/openstack_dashboard/dashboards/project/instances/templates/instances/_launch_customize_help.html
new file mode 100644
index 000000000..eb947e4b7
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/templates/instances/_launch_customize_help.html
@@ -0,0 +1,3 @@
+{% load i18n %}
+<p>{% blocktrans %}You can customize your instance after it's launched using the options available here.{% endblocktrans %}</p>
+<p>{% blocktrans %}The "Customization Script" field is analogous to "User Data" in other systems.{% endblocktrans %}</p>
diff --git a/openstack_dashboard/dashboards/project/instances/templates/instances/_launch_details_help.html b/openstack_dashboard/dashboards/project/instances/templates/instances/_launch_details_help.html
new file mode 100644
index 000000000..93a2154ef
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/templates/instances/_launch_details_help.html
@@ -0,0 +1,53 @@
+{% load i18n horizon humanize %}
+
+<p>{% blocktrans %}Specify the details for launching an instance.{% endblocktrans %}</p>
+<p>{% blocktrans %}The chart below shows the resources used by this project in relation to the project's quotas.{% endblocktrans %}</p>
+
+<h4>{% trans "Flavor Details" %}</h4>
+<table class="flavor_table table-striped">
+ <tbody>
+ <tr><td class="flavor_name">{% trans "Name" %}</td><td><span id="flavor_name"></span></td></tr>
+ <tr><td class="flavor_name">{% trans "VCPUs" %}</td><td><span id="flavor_vcpus"></span></td></tr>
+ <tr><td class="flavor_name">{% trans "Root Disk" %}</td><td><span id="flavor_disk"> </span> {% trans "GB" %}</td></tr>
+ <tr><td class="flavor_name">{% trans "Ephemeral Disk" %}</td><td><span id="flavor_ephemeral"></span> {% trans "GB" %}</td></tr>
+ <tr><td class="flavor_name">{% trans "Total Disk" %}</td><td><span id="flavor_disk_total"></span> {% trans "GB" %}</td></tr>
+ <tr><td class="flavor_name">{% trans "RAM" %}</td><td><span id="flavor_ram"></span> {% trans "MB" %}</td></tr>
+ </tbody>
+</table>
+
+<div class="quota-dynamic">
+ <h4>{% trans "Project Quotas" %}</h4>
+ <div class="quota_title clearfix">
+ <strong>{% trans "Number of Instances" %} <span>({{ usages.instances.used|intcomma }})</span></strong>
+ <p>{{ usages.instances.available|quota|intcomma }}</p>
+ </div>
+ <div id="quota_instances" class="quota_bar" data-progress-indicator-flavor data-quota-limit="{{ usages.instances.quota }}" data-quota-used="{{ usages.instances.used }}">
+ {% horizon_progress_bar usages.instances.used usages.instances.quota %}
+ </div>
+
+ <div class="quota_title clearfix">
+ <strong>{% trans "Number of VCPUs" %} <span>({{ usages.cores.used|intcomma }})</span></strong>
+ <p>{{ usages.cores.available|quota|intcomma }}</p>
+ </div>
+ <div id="quota_vcpus" class="quota_bar" data-progress-indicator-flavor data-quota-limit="{{ usages.cores.quota }}" data-quota-used="{{ usages.cores.used }}">
+ {% horizon_progress_bar usages.cores.used usages.cores.quota %}
+ </div>
+
+ <div class="quota_title clearfix">
+ <strong>{% trans "Total RAM" %} <span>({{ usages.ram.used|intcomma }} {% trans "MB" %})</span></strong>
+ <p>{{ usages.ram.available|quota:"MB"|intcomma }}</p>
+ </div>
+ <div id="quota_ram" data-progress-indicator-flavor data-quota-limit="{{ usages.ram.quota }}" data-quota-used="{{ usages.ram.used }}" class="quota_bar">
+ {% horizon_progress_bar usages.ram.used usages.ram.quota %}
+ </div>
+</div>
+
+<script type="text/javascript" charset="utf-8">
+ if(typeof horizon.Quota !== 'undefined') {
+ horizon.Quota.initWithFlavors({{ flavors|safe|default:"{}" }});
+ } else {
+ addHorizonLoadEvent(function() {
+ horizon.Quota.initWithFlavors({{ flavors|safe|default:"{}" }});
+ });
+ }
+</script>
diff --git a/openstack_dashboard/dashboards/project/instances/templates/instances/_launch_volumes_help.html b/openstack_dashboard/dashboards/project/instances/templates/instances/_launch_volumes_help.html
new file mode 100644
index 000000000..26f4429cb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/templates/instances/_launch_volumes_help.html
@@ -0,0 +1,3 @@
+{% load i18n horizon %}
+
+<p>{% blocktrans %}An instance can be launched with varying types of attached storage. You may select from those options here.{% endblocktrans %}</p>
diff --git a/openstack_dashboard/dashboards/project/instances/templates/instances/_update.html b/openstack_dashboard/dashboards/project/instances/templates/instances/_update.html
new file mode 100644
index 000000000..996435f1e
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/templates/instances/_update.html
@@ -0,0 +1,24 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}update_instance_form{% endblock %}
+{% block form_action %}{% url horizon:project:instances:update instance_id %}{% endblock %}
+
+{% block modal-header %}{% trans "Edit Instance" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description:" %}</h3>
+ <p>{% trans "You may update the editable properties of your instance here." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Save Changes" %}" />
+ <a href="{% url horizon:project:instances:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/instances/templates/instances/detail.html b/openstack_dashboard/dashboards/project/instances/templates/instances/detail.html
new file mode 100644
index 000000000..82f1e0ee0
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/templates/instances/detail.html
@@ -0,0 +1,15 @@
+{% extends 'base.html' %}
+{% load i18n sizeformat %}
+{% block title %}{% trans "Instance Detail" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title="Instance Detail: "|add:instance.name %}
+{% endblock page_header %}
+
+{% block main %}
+<div class="row-fluid">
+ <div class="span12">
+ {{ tab_group.render }}
+ </div>
+</div>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/instances/templates/instances/index.html b/openstack_dashboard/dashboards/project/instances/templates/instances/index.html
new file mode 100644
index 000000000..a47f1e5da
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/templates/instances/index.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Instances" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Instances") %}
+{% endblock page_header %}
+
+{% block main %}
+ {{ table.render }}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/instances/templates/instances/launch.html b/openstack_dashboard/dashboards/project/instances/templates/instances/launch.html
new file mode 100644
index 000000000..6353e056c
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/templates/instances/launch.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Launch Instance" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Launch Instance") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'horizon/common/_workflow.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/instances/templates/instances/update.html b/openstack_dashboard/dashboards/project/instances/templates/instances/update.html
new file mode 100644
index 000000000..aba3dc9ab
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/templates/instances/update.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Update Instance" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Update Instance") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'project/instances/_update.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/instances/tests.py b/openstack_dashboard/dashboards/project/instances/tests.py
new file mode 100644
index 000000000..43ef81fa1
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/tests.py
@@ -0,0 +1,980 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 import http
+from django.core.urlresolvers import reverse
+from django.utils.http import urlencode
+from django.utils.datastructures import SortedDict
+
+from mox import IsA, IgnoreArg
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+from .tabs import InstanceDetailTabs
+from .workflows import LaunchInstance
+
+
+INDEX_URL = reverse('horizon:project:instances:index')
+
+
+class InstanceTests(test.TestCase):
+ @test.create_stubs({api: ('flavor_list', 'server_list',)})
+ def test_index(self):
+ api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(
+ reverse('horizon:project:instances:index'))
+
+ self.assertTemplateUsed(res,
+ 'project/instances/index.html')
+ instances = res.context['instances_table'].data
+
+ self.assertItemsEqual(instances, self.servers.list())
+
+ @test.create_stubs({api: ('server_list',)})
+ def test_index_server_list_exception(self):
+ api.server_list(IsA(http.HttpRequest)).AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:project:instances:index'))
+
+ self.assertTemplateUsed(res, 'project/instances/index.html')
+ self.assertEqual(len(res.context['instances_table'].data), 0)
+ self.assertMessageCount(res, error=1)
+
+ @test.create_stubs({api: ('flavor_list', 'server_list', 'flavor_get',)})
+ def test_index_flavor_list_exception(self):
+ servers = self.servers.list()
+ flavors = self.flavors.list()
+ full_flavors = SortedDict([(f.id, f) for f in flavors])
+
+ api.server_list(IsA(http.HttpRequest)).AndReturn(servers)
+ api.flavor_list(IsA(http.HttpRequest)).AndRaise(self.exceptions.nova)
+ for server in servers:
+ api.flavor_get(IsA(http.HttpRequest), server.flavor["id"]). \
+ AndReturn(full_flavors[server.flavor["id"]])
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:project:instances:index'))
+
+ self.assertTemplateUsed(res, 'project/instances/index.html')
+ instances = res.context['instances_table'].data
+
+ self.assertItemsEqual(instances, self.servers.list())
+
+ @test.create_stubs({api: ('flavor_list', 'server_list', 'flavor_get',)})
+ def test_index_flavor_get_exception(self):
+ servers = self.servers.list()
+ flavors = self.flavors.list()
+ max_id = max([int(flavor.id) for flavor in flavors])
+ for server in servers:
+ max_id += 1
+ server.flavor["id"] = max_id
+
+ api.server_list(IsA(http.HttpRequest)).AndReturn(servers)
+ api.flavor_list(IsA(http.HttpRequest)).AndReturn(flavors)
+ for server in servers:
+ api.flavor_get(IsA(http.HttpRequest), server.flavor["id"]). \
+ AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:project:instances:index'))
+
+ instances = res.context['instances_table'].data
+
+ self.assertTemplateUsed(res, 'project/instances/index.html')
+ self.assertMessageCount(res, error=len(servers))
+ self.assertItemsEqual(instances, self.servers.list())
+
+ @test.create_stubs({api: ('server_list',
+ 'flavor_list',
+ 'server_delete',)})
+ def test_terminate_instance(self):
+ server = self.servers.first()
+
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+ api.flavor_list(IgnoreArg()).AndReturn(self.flavors.list())
+ api.server_delete(IsA(http.HttpRequest), server.id)
+
+ self.mox.ReplayAll()
+
+ formData = {'action': 'instances__terminate__%s' % server.id}
+ res = self.client.post(INDEX_URL, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('server_list',
+ 'flavor_list',
+ 'server_delete',)})
+ def test_terminate_instance_exception(self):
+ server = self.servers.first()
+
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+ api.flavor_list(IgnoreArg()).AndReturn(self.flavors.list())
+ api.server_delete(IsA(http.HttpRequest), server.id) \
+ .AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ formData = {'action': 'instances__terminate__%s' % server.id}
+ res = self.client.post(INDEX_URL, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('server_pause',
+ 'server_list',
+ 'flavor_list',)})
+ def test_pause_instance(self):
+ server = self.servers.first()
+
+ api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+ api.server_pause(IsA(http.HttpRequest), server.id)
+
+ self.mox.ReplayAll()
+
+ formData = {'action': 'instances__pause__%s' % server.id}
+ res = self.client.post(INDEX_URL, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('server_pause',
+ 'server_list',
+ 'flavor_list',)})
+ def test_pause_instance_exception(self):
+ server = self.servers.first()
+
+ api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+ api.server_pause(IsA(http.HttpRequest), server.id) \
+ .AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ formData = {'action': 'instances__pause__%s' % server.id}
+ res = self.client.post(INDEX_URL, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('server_unpause',
+ 'server_list',
+ 'flavor_list',)})
+ def test_unpause_instance(self):
+ server = self.servers.first()
+ server.status = "PAUSED"
+
+ api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+ api.server_unpause(IsA(http.HttpRequest), server.id)
+
+ self.mox.ReplayAll()
+
+ formData = {'action': 'instances__pause__%s' % server.id}
+ res = self.client.post(INDEX_URL, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('server_unpause',
+ 'server_list',
+ 'flavor_list',)})
+ def test_unpause_instance_exception(self):
+ server = self.servers.first()
+ server.status = "PAUSED"
+
+ api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+ api.server_unpause(IsA(http.HttpRequest), server.id) \
+ .AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ formData = {'action': 'instances__pause__%s' % server.id}
+ res = self.client.post(INDEX_URL, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('server_reboot',
+ 'server_list',
+ 'flavor_list',)})
+ def test_reboot_instance(self):
+ server = self.servers.first()
+
+ api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+ api.server_reboot(IsA(http.HttpRequest), server.id)
+
+ self.mox.ReplayAll()
+
+ formData = {'action': 'instances__reboot__%s' % server.id}
+ res = self.client.post(INDEX_URL, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('server_reboot',
+ 'server_list',
+ 'flavor_list',)})
+ def test_reboot_instance_exception(self):
+ server = self.servers.first()
+
+ api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+ api.server_reboot(IsA(http.HttpRequest), server.id) \
+ .AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ formData = {'action': 'instances__reboot__%s' % server.id}
+ res = self.client.post(INDEX_URL, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('server_suspend',
+ 'server_list',
+ 'flavor_list',)})
+ def test_suspend_instance(self):
+ server = self.servers.first()
+
+ api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+ api.server_suspend(IsA(http.HttpRequest), unicode(server.id))
+
+ self.mox.ReplayAll()
+
+ formData = {'action': 'instances__suspend__%s' % server.id}
+ res = self.client.post(INDEX_URL, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('server_suspend',
+ 'server_list',
+ 'flavor_list',)})
+ def test_suspend_instance_exception(self):
+ server = self.servers.first()
+
+ api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+ api.server_suspend(IsA(http.HttpRequest),
+ unicode(server.id)).AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ formData = {'action': 'instances__suspend__%s' % server.id}
+ res = self.client.post(INDEX_URL, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('server_resume',
+ 'server_list',
+ 'flavor_list',)})
+ def test_resume_instance(self):
+ server = self.servers.first()
+ server.status = "SUSPENDED"
+
+ api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+ api.server_resume(IsA(http.HttpRequest), unicode(server.id))
+
+ self.mox.ReplayAll()
+
+ formData = {'action': 'instances__suspend__%s' % server.id}
+ res = self.client.post(INDEX_URL, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('server_resume',
+ 'server_list',
+ 'flavor_list',)})
+ def test_resume_instance_exception(self):
+ server = self.servers.first()
+ server.status = "SUSPENDED"
+
+ api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+ api.server_resume(IsA(http.HttpRequest),
+ unicode(server.id)).AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ formData = {'action': 'instances__suspend__%s' % server.id}
+ res = self.client.post(INDEX_URL, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ("server_get",
+ "volume_instance_list",
+ "flavor_get",
+ "server_security_groups")})
+ def test_instance_details_volumes(self):
+ server = self.servers.first()
+ volumes = [self.volumes.list()[1]]
+
+ api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
+ api.volume_instance_list(IsA(http.HttpRequest),
+ server.id).AndReturn(volumes)
+ api.flavor_get(IsA(http.HttpRequest),
+ server.flavor['id']).AndReturn(self.flavors.first())
+ api.server_security_groups(IsA(http.HttpRequest),
+ server.id).AndReturn(self.security_groups.first())
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:instances:detail',
+ args=[server.id])
+ res = self.client.get(url)
+
+ self.assertItemsEqual(res.context['instance'].volumes, volumes)
+
+ @test.create_stubs({api: ("server_get",
+ "volume_instance_list",
+ "flavor_get",
+ "server_security_groups")})
+ def test_instance_details_volume_sorting(self):
+ server = self.servers.first()
+ volumes = self.volumes.list()[1:3]
+
+ api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
+ api.volume_instance_list(IsA(http.HttpRequest),
+ server.id).AndReturn(volumes)
+ api.flavor_get(IsA(http.HttpRequest),
+ server.flavor['id']).AndReturn(self.flavors.first())
+ api.server_security_groups(IsA(http.HttpRequest),
+ server.id).AndReturn(self.security_groups.first())
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:instances:detail',
+ args=[server.id])
+ res = self.client.get(url)
+
+ self.assertItemsEqual(res.context['instance'].volumes, volumes)
+ self.assertEquals(res.context['instance'].volumes[0].device,
+ "/dev/hda")
+ self.assertEquals(res.context['instance'].volumes[1].device,
+ "/dev/hdk")
+
+ @test.create_stubs({api: ("server_get",
+ "volume_instance_list",
+ "flavor_get",
+ "server_security_groups",)})
+ def test_instance_details_metadata(self):
+ server = self.servers.first()
+
+ api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
+ api.volume_instance_list(IsA(http.HttpRequest),
+ server.id).AndReturn([])
+ api.flavor_get(IsA(http.HttpRequest),
+ server.flavor['id']).AndReturn(self.flavors.first())
+ api.server_security_groups(IsA(http.HttpRequest),
+ server.id).AndReturn(self.security_groups.list())
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:instances:detail',
+ args=[server.id])
+ tg = InstanceDetailTabs(self.request, instance=server)
+ qs = "?%s=%s" % (tg.param_name, tg.get_tab("overview").get_id())
+ res = self.client.get(url + qs)
+
+ self.assertContains(res, "<dd>keyName</dd>", 1)
+ self.assertContains(res, "<dt>someMetaLabel</dt>", 1)
+ self.assertContains(res, "<dd>someMetaData</dd>", 1)
+ self.assertContains(res, "<dt>some&lt;b&gt;html&lt;/b&gt;label</dt>",
+ 1)
+ self.assertContains(res, "<dd>&lt;!--</dd>", 1)
+ self.assertContains(res, "<dt>empty</dt>", 1)
+ self.assertContains(res, "<dd><em>N/A</em></dd>", 1)
+
+ @test.create_stubs({api: ('server_console_output',)})
+ def test_instance_log(self):
+ server = self.servers.first()
+ CONSOLE_OUTPUT = 'output'
+
+ api.server_console_output(IsA(http.HttpRequest),
+ server.id, tail_length=None) \
+ .AndReturn(CONSOLE_OUTPUT)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:instances:console',
+ args=[server.id])
+ tg = InstanceDetailTabs(self.request, instance=server)
+ qs = "?%s=%s" % (tg.param_name, tg.get_tab("log").get_id())
+ res = self.client.get(url + qs)
+
+ self.assertNoMessages()
+ self.assertIsInstance(res, http.HttpResponse)
+ self.assertContains(res, CONSOLE_OUTPUT)
+
+ @test.create_stubs({api: ('server_console_output',)})
+ def test_instance_log_exception(self):
+ server = self.servers.first()
+
+ api.server_console_output(IsA(http.HttpRequest),
+ server.id, tail_length=None) \
+ .AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:instances:console',
+ args=[server.id])
+ tg = InstanceDetailTabs(self.request, instance=server)
+ qs = "?%s=%s" % (tg.param_name, tg.get_tab("log").get_id())
+ res = self.client.get(url + qs)
+
+ self.assertContains(res, "Unable to get log for")
+
+ def test_instance_vnc(self):
+ server = self.servers.first()
+ CONSOLE_OUTPUT = '/vncserver'
+
+ console_mock = self.mox.CreateMock(api.VNCConsole)
+ console_mock.url = CONSOLE_OUTPUT
+
+ self.mox.StubOutWithMock(api, 'server_vnc_console')
+ self.mox.StubOutWithMock(api, 'server_get')
+ api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
+ api.server_vnc_console(IgnoreArg(), server.id).AndReturn(console_mock)
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:instances:vnc',
+ args=[server.id])
+ res = self.client.get(url)
+ redirect = CONSOLE_OUTPUT + '&title=%s(1)' % server.name
+ self.assertRedirectsNoFollow(res, redirect)
+
+ @test.create_stubs({api: ('server_vnc_console',)})
+ def test_instance_vnc_exception(self):
+ server = self.servers.first()
+
+ api.server_vnc_console(IsA(http.HttpRequest), server.id) \
+ .AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:instances:vnc',
+ args=[server.id])
+ res = self.client.get(url)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('server_get',
+ 'snapshot_create',
+ 'snapshot_list_detailed',
+ 'image_list_detailed',
+ 'volume_snapshot_list',
+ 'server_list',
+ 'flavor_list',
+ 'server_delete',)})
+ def test_create_instance_snapshot(self):
+ server = self.servers.first()
+
+ api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
+ api.snapshot_create(IsA(http.HttpRequest),
+ server.id,
+ "snapshot1").AndReturn(self.snapshots.first())
+
+ api.snapshot_list_detailed(IsA(http.HttpRequest),
+ marker=None).AndReturn([[], False])
+ api.image_list_detailed(IsA(http.HttpRequest),
+ marker=None).AndReturn([[], False])
+ api.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
+
+ self.mox.ReplayAll()
+
+ formData = {'instance_id': server.id,
+ 'method': 'CreateSnapshot',
+ 'name': 'snapshot1'}
+ url = reverse('horizon:project:images_and_snapshots:snapshots:create',
+ args=[server.id])
+ redir_url = reverse('horizon:project:images_and_snapshots:index')
+ res = self.client.post(url, formData)
+ self.assertRedirects(res, redir_url)
+
+ @test.create_stubs({api: ('server_get',)})
+ def test_instance_update_get(self):
+ server = self.servers.first()
+
+ api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:instances:update', args=[server.id])
+ res = self.client.get(url)
+
+ self.assertTemplateUsed(res, 'project/instances/update.html')
+
+ @test.create_stubs({api: ('server_get',)})
+ def test_instance_update_get_server_get_exception(self):
+ server = self.servers.first()
+
+ api.server_get(IsA(http.HttpRequest), server.id) \
+ .AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:instances:update',
+ args=[server.id])
+ res = self.client.get(url)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('server_get', 'server_update')})
+ def test_instance_update_post(self):
+ server = self.servers.first()
+
+ api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
+ api.server_update(IsA(http.HttpRequest),
+ server.id,
+ server.name).AndReturn(server)
+
+ self.mox.ReplayAll()
+
+ formData = {'method': 'UpdateInstance',
+ 'instance': server.id,
+ 'name': server.name,
+ 'tenant_id': self.tenant.id}
+ url = reverse('horizon:project:instances:update',
+ args=[server.id])
+ res = self.client.post(url, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api: ('server_get', 'server_update')})
+ def test_instance_update_post_api_exception(self):
+ server = self.servers.first()
+
+ api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
+ api.server_update(IsA(http.HttpRequest), server.id, server.name) \
+ .AndRaise(self.exceptions.nova)
+
+ self.mox.ReplayAll()
+
+ formData = {'method': 'UpdateInstance',
+ 'instance': server.id,
+ 'name': server.name,
+ 'tenant_id': self.tenant.id}
+ url = reverse('horizon:project:instances:update',
+ args=[server.id])
+ res = self.client.post(url, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.nova: ('tenant_quota_usages',
+ 'flavor_list',
+ 'keypair_list',
+ 'security_group_list',
+ 'volume_snapshot_list',
+ 'volume_list',),
+ api.quantum: ('network_list',),
+ api.glance: ('image_list_detailed',)})
+ def test_launch_instance_get(self):
+ quota_usages = self.quota_usages.first()
+ image = self.images.first()
+
+ api.nova.volume_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.volumes.list())
+ api.nova.volume_snapshot_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.volumes.list())
+ api.glance.image_list_detailed(IsA(http.HttpRequest),
+ filters={'is_public': True,
+ 'status': 'active'}) \
+ .AndReturn([self.images.list(), False])
+ api.glance.image_list_detailed(IsA(http.HttpRequest),
+ filters={'property-owner_id': self.tenant.id,
+ 'status': 'active'}) \
+ .AndReturn([[], False])
+ api.quantum.network_list(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ shared=False) \
+ .AndReturn(self.networks.list()[:1])
+ api.quantum.network_list(IsA(http.HttpRequest),
+ shared=True) \
+ .AndReturn(self.networks.list()[1:])
+ api.nova.tenant_quota_usages(IsA(http.HttpRequest)) \
+ .AndReturn(quota_usages)
+ api.nova.flavor_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.flavors.list())
+ api.nova.flavor_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.flavors.list())
+ api.nova.keypair_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.keypairs.list())
+ api.nova.security_group_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.security_groups.list())
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:instances:launch')
+ params = urlencode({"source_type": "image_id",
+ "source_id": image.id})
+ res = self.client.get("%s?%s" % (url, params))
+
+ workflow = res.context['workflow']
+ self.assertTemplateUsed(res,
+ 'project/instances/launch.html')
+ self.assertEqual(res.context['workflow'].name, LaunchInstance.name)
+ step = workflow.get_step("setinstancedetailsaction")
+ self.assertEqual(step.action.initial['image_id'], image.id)
+ self.assertQuerysetEqual(workflow.steps,
+ ['<SetInstanceDetails: setinstancedetailsaction>',
+ '<SetAccessControls: setaccesscontrolsaction>',
+ '<SetNetwork: setnetworkaction>',
+ '<VolumeOptions: volumeoptionsaction>',
+ '<PostCreationStep: customizeaction>'])
+
+ @test.create_stubs({api.glance: ('image_list_detailed',),
+ api.quantum: ('network_list',),
+ api.nova: ('flavor_list',
+ 'keypair_list',
+ 'security_group_list',
+ 'volume_list',
+ 'volume_snapshot_list',
+ 'tenant_quota_usages',
+ 'server_create',)})
+ def test_launch_instance_post(self):
+ flavor = self.flavors.first()
+ image = self.images.first()
+ keypair = self.keypairs.first()
+ server = self.servers.first()
+ volume = self.volumes.first()
+ sec_group = self.security_groups.first()
+ customization_script = 'user data'
+ device_name = u'vda'
+ volume_choice = "%s:vol" % volume.id
+ block_device_mapping = {device_name: u"%s::0" % volume_choice}
+ nics = [{"net-id": self.networks.first().id, "v4-fixed-ip": ''}]
+
+ api.nova.flavor_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.flavors.list())
+ api.nova.keypair_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.keypairs.list())
+ api.nova.security_group_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.security_groups.list())
+ api.glance.image_list_detailed(IsA(http.HttpRequest),
+ filters={'is_public': True,
+ 'status': 'active'}) \
+ .AndReturn([self.images.list(), False])
+ api.glance.image_list_detailed(IsA(http.HttpRequest),
+ filters={'property-owner_id': self.tenant.id,
+ 'status': 'active'}) \
+ .AndReturn([[], False])
+ api.quantum.network_list(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ shared=False) \
+ .AndReturn(self.networks.list()[:1])
+ api.quantum.network_list(IsA(http.HttpRequest),
+ shared=True) \
+ .AndReturn(self.networks.list()[1:])
+ api.nova.volume_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.volumes.list())
+ api.nova.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
+ api.nova.server_create(IsA(http.HttpRequest),
+ server.name,
+ image.id,
+ flavor.id,
+ keypair.name,
+ customization_script,
+ [sec_group.name],
+ block_device_mapping,
+ nics=nics,
+ instance_count=IsA(int))
+
+ self.mox.ReplayAll()
+
+ form_data = {'flavor': flavor.id,
+ 'source_type': 'image_id',
+ 'image_id': image.id,
+ 'keypair': keypair.name,
+ 'name': server.name,
+ 'customization_script': customization_script,
+ 'project_id': self.tenants.first().id,
+ 'user_id': self.user.id,
+ 'groups': sec_group.name,
+ 'volume_type': 'volume_id',
+ 'volume_id': volume_choice,
+ 'device_name': device_name,
+ 'network': self.networks.first().id,
+ 'count': 1}
+ url = reverse('horizon:project:instances:launch')
+ res = self.client.post(url, form_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.glance: ('image_list_detailed',),
+ api.quantum: ('network_list',),
+ api.nova: ('flavor_list',
+ 'keypair_list',
+ 'security_group_list',
+ 'volume_list',
+ 'tenant_quota_usages',
+ 'volume_snapshot_list',)})
+ def test_launch_instance_post_no_images_available(self):
+ flavor = self.flavors.first()
+ keypair = self.keypairs.first()
+ server = self.servers.first()
+ volume = self.volumes.first()
+ sec_group = self.security_groups.first()
+ customization_script = 'user data'
+ device_name = u'vda'
+ volume_choice = "%s:vol" % volume.id
+
+ api.nova.flavor_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.flavors.list())
+ api.nova.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn({})
+ api.glance.image_list_detailed(IsA(http.HttpRequest),
+ filters={'is_public': True,
+ 'status': 'active'}) \
+ .AndReturn([[], False])
+ api.glance.image_list_detailed(IsA(http.HttpRequest),
+ filters={'property-owner_id': self.tenant.id,
+ 'status': 'active'}) \
+ .AndReturn([[], False])
+ api.quantum.network_list(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ shared=False) \
+ .AndReturn(self.networks.list()[:1])
+ api.quantum.network_list(IsA(http.HttpRequest),
+ shared=True) \
+ .AndReturn(self.networks.list()[1:])
+ api.nova.flavor_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.flavors.list())
+ api.nova.keypair_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.keypairs.list())
+ api.nova.security_group_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.security_groups.list())
+ api.nova.volume_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.volumes.list())
+ api.nova.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
+
+ self.mox.ReplayAll()
+
+ form_data = {'flavor': flavor.id,
+ 'source_type': 'image_id',
+ 'image_id': '',
+ 'keypair': keypair.name,
+ 'name': server.name,
+ 'customization_script': customization_script,
+ 'project_id': self.tenants.first().id,
+ 'user_id': self.user.id,
+ 'groups': sec_group.name,
+ 'volume_type': 'volume_id',
+ 'volume_id': volume_choice,
+ 'device_name': device_name,
+ 'count': 1}
+ url = reverse('horizon:project:instances:launch')
+ res = self.client.post(url, form_data)
+
+ self.assertFormErrors(res, 1, 'There are no image sources available; '
+ 'you must first create an image before '
+ 'attempting to launch an instance.')
+ self.assertTemplateUsed(res,
+ 'project/instances/launch.html')
+
+ @test.create_stubs({api.glance: ('image_list_detailed',),
+ api.quantum: ('network_list',),
+ api.nova: ('tenant_quota_usages',
+ 'flavor_list',
+ 'keypair_list',
+ 'volume_list',
+ 'security_group_list',
+ 'volume_snapshot_list',)})
+ def test_launch_flavorlist_error(self):
+ api.nova.volume_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.volumes.list())
+ api.nova.volume_snapshot_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.volumes.list())
+ api.glance.image_list_detailed(IsA(http.HttpRequest),
+ filters={'is_public': True,
+ 'status': 'active'}) \
+ .AndReturn([self.images.list(), False])
+ api.glance.image_list_detailed(IsA(http.HttpRequest),
+ filters={'property-owner_id': self.tenant.id,
+ 'status': 'active'}) \
+ .AndReturn([[], False])
+ api.quantum.network_list(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ shared=False) \
+ .AndReturn(self.networks.list()[:1])
+ api.quantum.network_list(IsA(http.HttpRequest),
+ shared=True) \
+ .AndReturn(self.networks.list()[1:])
+ api.nova.tenant_quota_usages(IsA(http.HttpRequest)) \
+ .AndReturn(self.quota_usages.first())
+ api.nova.flavor_list(IsA(http.HttpRequest)) \
+ .AndRaise(self.exceptions.nova)
+ api.nova.flavor_list(IsA(http.HttpRequest)) \
+ .AndRaise(self.exceptions.nova)
+ api.nova.keypair_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.keypairs.list())
+ api.nova.security_group_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.security_groups.list())
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:instances:launch')
+ res = self.client.get(url)
+
+ self.assertTemplateUsed(res,
+ 'project/instances/launch.html')
+
+ @test.create_stubs({api.glance: ('image_list_detailed',),
+ api.quantum: ('network_list',),
+ api.nova: ('flavor_list',
+ 'keypair_list',
+ 'security_group_list',
+ 'volume_list',
+ 'server_create',
+ 'volume_snapshot_list',)})
+ def test_launch_form_keystone_exception(self):
+ flavor = self.flavors.first()
+ image = self.images.first()
+ keypair = self.keypairs.first()
+ server = self.servers.first()
+ sec_group = self.security_groups.first()
+ customization_script = 'userData'
+ nics = [{"net-id": self.networks.first().id, "v4-fixed-ip": ''}]
+
+ api.nova.volume_snapshot_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.volumes.list())
+ api.nova.flavor_list(IgnoreArg()).AndReturn(self.flavors.list())
+ api.nova.keypair_list(IgnoreArg()).AndReturn(self.keypairs.list())
+ api.nova.security_group_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.security_groups.list())
+ api.glance.image_list_detailed(IsA(http.HttpRequest),
+ filters={'is_public': True,
+ 'status': 'active'}) \
+ .AndReturn([self.images.list(), False])
+ api.glance.image_list_detailed(IsA(http.HttpRequest),
+ filters={'property-owner_id': self.tenant.id,
+ 'status': 'active'}) \
+ .AndReturn([[], False])
+ api.quantum.network_list(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ shared=False) \
+ .AndReturn(self.networks.list()[:1])
+ api.quantum.network_list(IsA(http.HttpRequest),
+ shared=True) \
+ .AndReturn(self.networks.list()[1:])
+ api.nova.volume_list(IgnoreArg()).AndReturn(self.volumes.list())
+ api.nova.server_create(IsA(http.HttpRequest),
+ server.name,
+ image.id,
+ flavor.id,
+ keypair.name,
+ customization_script,
+ [sec_group.name],
+ None,
+ nics=nics,
+ instance_count=IsA(int)) \
+ .AndRaise(self.exceptions.keystone)
+
+ self.mox.ReplayAll()
+
+ form_data = {'flavor': flavor.id,
+ 'source_type': 'image_id',
+ 'image_id': image.id,
+ 'keypair': keypair.name,
+ 'name': server.name,
+ 'customization_script': customization_script,
+ 'project_id': self.tenants.first().id,
+ 'user_id': self.user.id,
+ 'groups': sec_group.name,
+ 'volume_type': '',
+ 'network': self.networks.first().id,
+ 'count': 1}
+ url = reverse('horizon:project:instances:launch')
+ res = self.client.post(url, form_data)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.glance: ('image_list_detailed',),
+ api.quantum: ('network_list',),
+ api.nova: ('flavor_list',
+ 'keypair_list',
+ 'security_group_list',
+ 'volume_list',
+ 'tenant_quota_usages',
+ 'volume_snapshot_list',)})
+ def test_launch_form_instance_count_error(self):
+ flavor = self.flavors.first()
+ image = self.images.first()
+ keypair = self.keypairs.first()
+ server = self.servers.first()
+ volume = self.volumes.first()
+ sec_group = self.security_groups.first()
+ customization_script = 'user data'
+ device_name = u'vda'
+ volume_choice = "%s:vol" % volume.id
+
+ api.nova.flavor_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.flavors.list())
+ api.nova.keypair_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.keypairs.list())
+ api.nova.security_group_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.security_groups.list())
+ api.glance.image_list_detailed(IsA(http.HttpRequest),
+ filters={'is_public': True,
+ 'status': 'active'}) \
+ .AndReturn([self.images.list(), False])
+ api.glance.image_list_detailed(IsA(http.HttpRequest),
+ filters={'property-owner_id': self.tenant.id,
+ 'status': 'active'}) \
+ .AndReturn([[], False])
+ api.quantum.network_list(IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ shared=False) \
+ .AndReturn(self.networks.list()[:1])
+ api.quantum.network_list(IsA(http.HttpRequest),
+ shared=True) \
+ .AndReturn(self.networks.list()[1:])
+ api.nova.volume_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.volumes.list())
+ api.nova.volume_snapshot_list(IsA(http.HttpRequest)).AndReturn([])
+
+ api.nova.flavor_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.flavors.list())
+ api.nova.tenant_quota_usages(IsA(http.HttpRequest)) \
+ .AndReturn(self.quota_usages.first())
+
+ self.mox.ReplayAll()
+
+ form_data = {'flavor': flavor.id,
+ 'source_type': 'image_id',
+ 'image_id': image.id,
+ 'keypair': keypair.name,
+ 'name': server.name,
+ 'customization_script': customization_script,
+ 'project_id': self.tenants.first().id,
+ 'user_id': self.user.id,
+ 'groups': sec_group.name,
+ 'volume_type': 'volume_id',
+ 'volume_id': volume_choice,
+ 'device_name': device_name,
+ 'count': 0}
+ url = reverse('horizon:project:instances:launch')
+ res = self.client.post(url, form_data)
+
+ self.assertContains(res, "greater than or equal to 1")
diff --git a/openstack_dashboard/dashboards/project/instances/urls.py b/openstack_dashboard/dashboards/project/instances/urls.py
new file mode 100644
index 000000000..8ea1609a9
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/urls.py
@@ -0,0 +1,37 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import patterns, url
+
+from .views import IndexView, UpdateView, DetailView, LaunchInstanceView
+
+
+INSTANCES = r'^(?P<instance_id>[^/]+)/%s$'
+VIEW_MOD = 'openstack_dashboard.dashboards.project.instances.views'
+
+
+urlpatterns = patterns(VIEW_MOD,
+ url(r'^$', IndexView.as_view(), name='index'),
+ url(r'^launch$', LaunchInstanceView.as_view(), name='launch'),
+ url(r'^(?P<instance_id>[^/]+)/$', DetailView.as_view(), name='detail'),
+ url(INSTANCES % 'update', UpdateView.as_view(), name='update'),
+ url(INSTANCES % 'console', 'console', name='console'),
+ url(INSTANCES % 'vnc', 'vnc', name='vnc')
+)
diff --git a/openstack_dashboard/dashboards/project/instances/views.py b/openstack_dashboard/dashboards/project/instances/views.py
new file mode 100644
index 000000000..9cea06ecf
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/views.py
@@ -0,0 +1,187 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.
+
+"""
+Views for managing instances.
+"""
+import logging
+
+from django import http
+from django import shortcuts
+from django.core.urlresolvers import reverse, reverse_lazy
+from django.utils.datastructures import SortedDict
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import tabs
+from horizon import tables
+from horizon import workflows
+
+from openstack_dashboard import api
+from .forms import UpdateInstance
+from .tabs import InstanceDetailTabs
+from .tables import InstancesTable
+from .workflows import LaunchInstance
+
+
+LOG = logging.getLogger(__name__)
+
+
+class IndexView(tables.DataTableView):
+ table_class = InstancesTable
+ template_name = 'project/instances/index.html'
+
+ def get_data(self):
+ # Gather our instances
+ try:
+ instances = api.server_list(self.request)
+ except:
+ instances = []
+ exceptions.handle(self.request,
+ _('Unable to retrieve instances.'))
+ # Gather our flavors and correlate our instances to them
+ if instances:
+ try:
+ flavors = api.flavor_list(self.request)
+ except:
+ flavors = []
+ exceptions.handle(self.request, ignore=True)
+
+ full_flavors = SortedDict([(str(flavor.id), flavor)
+ for flavor in flavors])
+ # Loop through instances to get flavor info.
+ for instance in instances:
+ try:
+ flavor_id = instance.flavor["id"]
+ if flavor_id in full_flavors:
+ instance.full_flavor = full_flavors[flavor_id]
+ else:
+ # If the flavor_id is not in full_flavors list,
+ # get it via nova api.
+ instance.full_flavor = api.flavor_get(self.request,
+ flavor_id)
+ except:
+ msg = _('Unable to retrieve instance size information.')
+ exceptions.handle(self.request, msg)
+ return instances
+
+
+class LaunchInstanceView(workflows.WorkflowView):
+ workflow_class = LaunchInstance
+ template_name = "project/instances/launch.html"
+
+ def get_initial(self):
+ initial = super(LaunchInstanceView, self).get_initial()
+ initial['project_id'] = self.request.user.tenant_id
+ initial['user_id'] = self.request.user.id
+ return initial
+
+
+def console(request, instance_id):
+ try:
+ # TODO(jakedahn): clean this up once the api supports tailing.
+ tail = request.GET.get('length', None)
+ data = api.server_console_output(request,
+ instance_id,
+ tail_length=tail)
+ except:
+ data = _('Unable to get log for instance "%s".') % instance_id
+ exceptions.handle(request, ignore=True)
+ response = http.HttpResponse(mimetype='text/plain')
+ response.write(data)
+ response.flush()
+ return response
+
+
+def vnc(request, instance_id):
+ try:
+ console = api.server_vnc_console(request, instance_id)
+ instance = api.server_get(request, instance_id)
+ return shortcuts.redirect(console.url +
+ ("&title=%s(%s)" % (instance.name, instance_id)))
+ except:
+ redirect = reverse("horizon:project:instances:index")
+ msg = _('Unable to get VNC console for instance "%s".') % instance_id
+ exceptions.handle(request, msg, redirect=redirect)
+
+
+class UpdateView(forms.ModalFormView):
+ form_class = UpdateInstance
+ template_name = 'project/instances/update.html'
+ context_object_name = 'instance'
+ success_url = reverse_lazy("horizon:project:instances:index")
+
+ def get_context_data(self, **kwargs):
+ context = super(UpdateView, self).get_context_data(**kwargs)
+ context["instance_id"] = self.kwargs['instance_id']
+ return context
+
+ def get_object(self, *args, **kwargs):
+ if not hasattr(self, "_object"):
+ instance_id = self.kwargs['instance_id']
+ try:
+ self._object = api.server_get(self.request, instance_id)
+ except:
+ redirect = reverse("horizon:project:instances:index")
+ msg = _('Unable to retrieve instance details.')
+ exceptions.handle(self.request, msg, redirect=redirect)
+ return self._object
+
+ def get_initial(self):
+ return {'instance': self.kwargs['instance_id'],
+ 'tenant_id': self.request.user.tenant_id,
+ 'name': getattr(self.get_object(), 'name', '')}
+
+
+class DetailView(tabs.TabView):
+ tab_group_class = InstanceDetailTabs
+ template_name = 'project/instances/detail.html'
+
+ def get_context_data(self, **kwargs):
+ context = super(DetailView, self).get_context_data(**kwargs)
+ context["instance"] = self.get_data()
+ return context
+
+ def get_data(self):
+ if not hasattr(self, "_instance"):
+ try:
+ instance_id = self.kwargs['instance_id']
+ instance = api.server_get(self.request, instance_id)
+ instance.volumes = api.volume_instance_list(self.request,
+ instance_id)
+ # Sort by device name
+ instance.volumes.sort(key=lambda vol: vol.device)
+ instance.full_flavor = api.flavor_get(self.request,
+ instance.flavor["id"])
+ instance.security_groups = api.server_security_groups(
+ self.request, instance_id)
+ except:
+ redirect = reverse('horizon:project:instances:index')
+ exceptions.handle(self.request,
+ _('Unable to retrieve details for '
+ 'instance "%s".') % instance_id,
+ redirect=redirect)
+ self._instance = instance
+ return self._instance
+
+ def get_tabs(self, request, *args, **kwargs):
+ instance = self.get_data()
+ return self.tab_group_class(request, instance=instance, **kwargs)
diff --git a/openstack_dashboard/dashboards/project/instances/workflows.py b/openstack_dashboard/dashboards/project/instances/workflows.py
new file mode 100644
index 000000000..53b382319
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/instances/workflows.py
@@ -0,0 +1,511 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 json
+import logging
+
+from django.utils.text import normalize_newlines
+from django.utils.translation import ugettext as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import workflows
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class SelectProjectUserAction(workflows.Action):
+ project_id = forms.ChoiceField(label=_("Project"))
+ user_id = forms.ChoiceField(label=_("User"))
+
+ def __init__(self, request, *args, **kwargs):
+ super(SelectProjectUserAction, self).__init__(request, *args, **kwargs)
+ # Set our project choices
+ projects = [(tenant.id, tenant.name)
+ for tenant in request.user.authorized_tenants]
+ self.fields['project_id'].choices = projects
+
+ # Set our user options
+ users = [(request.user.id, request.user.username)]
+ self.fields['user_id'].choices = users
+
+ class Meta:
+ name = _("Project & User")
+ # Unusable permission so this is always hidden. However, we
+ # keep this step in the workflow for validation/verification purposes.
+ permissions = ("!",)
+
+
+class SelectProjectUser(workflows.Step):
+ action_class = SelectProjectUserAction
+ contributes = ("project_id", "user_id")
+
+
+class VolumeOptionsAction(workflows.Action):
+ VOLUME_CHOICES = (
+ ('', _("Don't boot from a volume.")),
+ ("volume_id", _("Boot from volume.")),
+ ("volume_snapshot_id", _("Boot from volume snapshot "
+ "(creates a new volume).")),
+ )
+ # Boot from volume options
+ volume_type = forms.ChoiceField(label=_("Volume Options"),
+ choices=VOLUME_CHOICES,
+ required=False)
+ volume_id = forms.ChoiceField(label=_("Volume"), required=False)
+ volume_snapshot_id = forms.ChoiceField(label=_("Volume Snapshot"),
+ required=False)
+ device_name = forms.CharField(label=_("Device Name"),
+ required=False,
+ initial="vda",
+ help_text=_("Volume mount point (e.g. 'vda' "
+ "mounts at '/dev/vda')."))
+ delete_on_terminate = forms.BooleanField(label=_("Delete on Terminate"),
+ initial=False,
+ required=False,
+ help_text=_("Delete volume on "
+ "instance terminate"))
+
+ class Meta:
+ name = _("Volume Options")
+ permissions = ('openstack.services.volume',)
+ help_text_template = ("project/instances/"
+ "_launch_volumes_help.html")
+
+ def clean(self):
+ cleaned_data = super(VolumeOptionsAction, self).clean()
+ volume_opt = cleaned_data.get('volume_type', None)
+
+ if volume_opt and not cleaned_data[volume_opt]:
+ raise forms.ValidationError(_('Please choose a volume, or select '
+ '%s.') % self.VOLUME_CHOICES[0][1])
+ return cleaned_data
+
+ def _get_volume_display_name(self, volume):
+ if hasattr(volume, "volume_id"):
+ vol_type = "snap"
+ visible_label = _("Snapshot")
+ else:
+ vol_type = "vol"
+ visible_label = _("Volume")
+ return (("%s:%s" % (volume.id, vol_type)),
+ ("%s - %s GB (%s)" % (volume.display_name,
+ volume.size,
+ visible_label)))
+
+ def populate_volume_id_choices(self, request, context):
+ volume_options = [("", _("Select Volume"))]
+ try:
+ volumes = [v for v in api.nova.volume_list(self.request)
+ if v.status == api.VOLUME_STATE_AVAILABLE]
+ volume_options.extend([self._get_volume_display_name(vol)
+ for vol in volumes])
+ except:
+ exceptions.handle(self.request,
+ _('Unable to retrieve list of volumes.'))
+ return volume_options
+
+ def populate_volume_snapshot_id_choices(self, request, context):
+ volume_options = [("", _("Select Volume Snapshot"))]
+ try:
+ snapshots = api.nova.volume_snapshot_list(self.request)
+ snapshots = [s for s in snapshots
+ if s.status == api.VOLUME_STATE_AVAILABLE]
+ volume_options.extend([self._get_volume_display_name(snap)
+ for snap in snapshots])
+ except:
+ exceptions.handle(self.request,
+ _('Unable to retrieve list of volume '
+ 'snapshots.'))
+
+ return volume_options
+
+
+class VolumeOptions(workflows.Step):
+ action_class = VolumeOptionsAction
+ depends_on = ("project_id", "user_id")
+ contributes = ("volume_type",
+ "volume_id",
+ "device_name", # Can be None for an image.
+ "delete_on_terminate")
+
+ def contribute(self, data, context):
+ context = super(VolumeOptions, self).contribute(data, context)
+ # Translate form input to context for volume values.
+ if "volume_type" in data and data["volume_type"]:
+ context['volume_id'] = data.get(data['volume_type'], None)
+
+ if not context.get("volume_type", ""):
+ context['volume_type'] = self.action.VOLUME_CHOICES[0][0]
+ context['volume_id'] = None
+ context['device_name'] = None
+ context['delete_on_terminate'] = None
+ return context
+
+
+class SetInstanceDetailsAction(workflows.Action):
+ SOURCE_TYPE_CHOICES = (
+ ("image_id", _("Image")),
+ ("instance_snapshot_id", _("Snapshot")),
+ )
+ source_type = forms.ChoiceField(label=_("Instance Source"),
+ choices=SOURCE_TYPE_CHOICES)
+ image_id = forms.ChoiceField(label=_("Image"), required=False)
+ instance_snapshot_id = forms.ChoiceField(label=_("Instance Snapshot"),
+ required=False)
+ name = forms.CharField(max_length=80, label=_("Instance Name"))
+ flavor = forms.ChoiceField(label=_("Flavor"),
+ help_text=_("Size of image to launch."))
+ count = forms.IntegerField(label=_("Instance Count"),
+ min_value=1,
+ initial=1,
+ help_text=_("Number of instances to launch."))
+
+ class Meta:
+ name = _("Details")
+ help_text_template = ("project/instances/"
+ "_launch_details_help.html")
+
+ def clean(self):
+ cleaned_data = super(SetInstanceDetailsAction, self).clean()
+
+ # Validate our instance source.
+ source = cleaned_data['source_type']
+ # There should always be at least one image_id choice, telling the user
+ # that there are "No Images Available" so we check for 2 here...
+ if source == 'image_id' and not \
+ filter(lambda x: x[0] != '', self.fields['image_id'].choices):
+ raise forms.ValidationError(_("There are no image sources "
+ "available; you must first create "
+ "an image before attempting to "
+ "launch an instance."))
+ if not cleaned_data[source]:
+ raise forms.ValidationError(_("Please select an option for the "
+ "instance source."))
+
+ # Prevent launching multiple instances with the same volume.
+ # TODO(gabriel): is it safe to launch multiple instances with
+ # a snapshot since it should be cloned to new volumes?
+ count = cleaned_data.get('count', 1)
+ volume_type = self.data.get('volume_type', None)
+ if volume_type and count > 1:
+ msg = _('Launching multiple instances is only supported for '
+ 'images and instance snapshots.')
+ raise forms.ValidationError(msg)
+
+ return cleaned_data
+
+ def _get_available_images(self, request, context):
+ project_id = context.get('project_id', None)
+ if not hasattr(self, "_public_images"):
+ public = {"is_public": True,
+ "status": "active"}
+ try:
+ public_images, _more = api.glance.image_list_detailed(request,
+ filters=public)
+ except:
+ public_images = []
+ exceptions.handle(request,
+ _("Unable to retrieve public images."))
+ self._public_images = public_images
+
+ # Preempt if we don't have a project_id yet.
+ if project_id is None:
+ setattr(self, "_images_for_%s" % project_id, [])
+
+ if not hasattr(self, "_images_for_%s" % project_id):
+ owner = {"property-owner_id": project_id,
+ "status": "active"}
+ try:
+ owned_images, _more = api.glance.image_list_detailed(request,
+ filters=owner)
+ except:
+ exceptions.handle(request,
+ _("Unable to retrieve images for "
+ "the current project."))
+ setattr(self, "_images_for_%s" % project_id, owned_images)
+
+ owned_images = getattr(self, "_images_for_%s" % project_id)
+ images = owned_images + self._public_images
+
+ # Remove duplicate images
+ image_ids = []
+ final_images = []
+ for image in images:
+ if image.id not in image_ids:
+ image_ids.append(image.id)
+ final_images.append(image)
+ return [image for image in final_images
+ if image.container_format not in ('aki', 'ari')]
+
+ def populate_image_id_choices(self, request, context):
+ images = self._get_available_images(request, context)
+ choices = [(image.id, image.name)
+ for image in images
+ if image.properties.get("image_type", '') != "snapshot"]
+ if choices:
+ choices.insert(0, ("", _("Select Image")))
+ else:
+ choices.insert(0, ("", _("No images available.")))
+ return choices
+
+ def populate_instance_snapshot_id_choices(self, request, context):
+ images = self._get_available_images(request, context)
+ choices = [(image.id, image.name)
+ for image in images
+ if image.properties.get("image_type", '') == "snapshot"]
+ if choices:
+ choices.insert(0, ("", _("Select Instance Snapshot")))
+ else:
+ choices.insert(0, ("", _("No snapshots available.")))
+ return choices
+
+ def populate_flavor_choices(self, request, context):
+ try:
+ flavors = api.nova.flavor_list(request)
+ flavor_list = [(flavor.id, "%s" % flavor.name)
+ for flavor in flavors]
+ except:
+ flavor_list = []
+ exceptions.handle(request,
+ _('Unable to retrieve instance flavors.'))
+ return sorted(flavor_list)
+
+ def get_help_text(self):
+ extra = {}
+ try:
+ extra['usages'] = api.nova.tenant_quota_usages(self.request)
+ extra['usages_json'] = json.dumps(extra['usages'])
+ flavors = json.dumps([f._info for f in
+ api.nova.flavor_list(self.request)])
+ extra['flavors'] = flavors
+ except:
+ exceptions.handle(self.request,
+ _("Unable to retrieve quota information."))
+ return super(SetInstanceDetailsAction, self).get_help_text(extra)
+
+
+class SetInstanceDetails(workflows.Step):
+ action_class = SetInstanceDetailsAction
+ contributes = ("source_type", "source_id", "name", "count", "flavor")
+
+ def prepare_action_context(self, request, context):
+ if 'source_type' in context and 'source_id' in context:
+ context[context['source_type']] = context['source_id']
+ return context
+
+ def contribute(self, data, context):
+ context = super(SetInstanceDetails, self).contribute(data, context)
+ # Allow setting the source dynamically.
+ if ("source_type" in context and "source_id" in context
+ and context["source_type"] not in context):
+ context[context["source_type"]] = context["source_id"]
+
+ # Translate form input to context for source values.
+ if "source_type" in data:
+ context["source_id"] = data.get(data['source_type'], None)
+
+ return context
+
+
+KEYPAIR_IMPORT_URL = "horizon:project:access_and_security:keypairs:import"
+
+
+class SetAccessControlsAction(workflows.Action):
+ keypair = forms.DynamicChoiceField(label=_("Keypair"),
+ required=False,
+ help_text=_("Which keypair to use for "
+ "authentication."),
+ add_item_link=KEYPAIR_IMPORT_URL)
+ groups = forms.MultipleChoiceField(label=_("Security Groups"),
+ required=True,
+ initial=["default"],
+ widget=forms.CheckboxSelectMultiple(),
+ help_text=_("Launch instance in these "
+ "security groups."))
+
+ class Meta:
+ name = _("Access & Security")
+ help_text = _("Control access to your instance via keypairs, "
+ "security groups, and other mechanisms.")
+
+ def populate_keypair_choices(self, request, context):
+ try:
+ keypairs = api.nova.keypair_list(request)
+ keypair_list = [(kp.name, kp.name) for kp in keypairs]
+ except:
+ keypair_list = []
+ exceptions.handle(request,
+ _('Unable to retrieve keypairs.'))
+ if keypair_list:
+ keypair_list.insert(0, ("", _("Select a keypair")))
+ else:
+ keypair_list = (("", _("No keypairs available.")),)
+ return keypair_list
+
+ def populate_groups_choices(self, request, context):
+ try:
+ groups = api.nova.security_group_list(request)
+ security_group_list = [(sg.name, sg.name) for sg in groups]
+ except:
+ exceptions.handle(request,
+ _('Unable to retrieve list of security groups'))
+ security_group_list = []
+ return security_group_list
+
+
+class SetAccessControls(workflows.Step):
+ action_class = SetAccessControlsAction
+ depends_on = ("project_id", "user_id")
+ contributes = ("keypair_id", "security_group_ids")
+
+ def contribute(self, data, context):
+ if data:
+ post = self.workflow.request.POST
+ context['security_group_ids'] = post.getlist("groups")
+ context['keypair_id'] = data.get("keypair", "")
+ return context
+
+
+class CustomizeAction(workflows.Action):
+ customization_script = forms.CharField(widget=forms.Textarea,
+ label=_("Customization Script"),
+ required=False,
+ help_text=_("A script or set of "
+ "commands to be "
+ "executed after the "
+ "instance has been "
+ "built (max 16kb)."))
+
+ class Meta:
+ name = _("Post-Creation")
+ help_text_template = ("project/instances/"
+ "_launch_customize_help.html")
+
+
+class PostCreationStep(workflows.Step):
+ action_class = CustomizeAction
+ contributes = ("customization_script",)
+
+
+class SetNetworkAction(workflows.Action):
+ network = forms.MultipleChoiceField(label=_("Networks"),
+ required=True,
+ widget=forms.CheckboxSelectMultiple(),
+ help_text=_("Launch instance with"
+ "these networks"))
+
+ class Meta:
+ name = _("Networking")
+ permissions = ('openstack.services.network',)
+ help_text = _("Select networks for your instance.")
+
+ def populate_network_choices(self, request, context):
+ try:
+ tenant_id = self.request.user.tenant_id
+ networks = api.quantum.network_list_for_tenant(request, tenant_id)
+ for n in networks:
+ n.set_id_as_name_if_empty()
+ network_list = [(network.id, network.name) for network in networks]
+ except:
+ network_list = []
+ exceptions.handle(request,
+ _('Unable to retrieve networks.'))
+ return network_list
+
+
+class SetNetwork(workflows.Step):
+ action_class = SetNetworkAction
+ contributes = ("network_id",)
+
+ def contribute(self, data, context):
+ if data:
+ networks = self.workflow.request.POST.getlist("network")
+ # If no networks are explicitly specified, network list
+ # contains an empty string, so remove it.
+ networks = [n for n in networks if n != '']
+ if networks:
+ context['network_id'] = networks
+ return context
+
+
+class LaunchInstance(workflows.Workflow):
+ slug = "launch_instance"
+ name = _("Launch Instance")
+ finalize_button_name = _("Launch")
+ success_message = _('Launched %(count)s named "%(name)s".')
+ failure_message = _('Unable to launch %(count)s named "%(name)s".')
+ success_url = "horizon:project:instances:index"
+ default_steps = (SelectProjectUser,
+ SetInstanceDetails,
+ SetAccessControls,
+ SetNetwork,
+ VolumeOptions,
+ PostCreationStep)
+
+ def format_status_message(self, message):
+ name = self.context.get('name', 'unknown instance')
+ count = self.context.get('count', 1)
+ if int(count) > 1:
+ return message % {"count": _("%s instances") % count,
+ "name": name}
+ else:
+ return message % {"count": _("instance"), "name": name}
+
+ def handle(self, request, context):
+ custom_script = context.get('customization_script', '')
+
+ # Determine volume mapping options
+ if context.get('volume_type', None):
+ if(context['delete_on_terminate']):
+ del_on_terminate = 1
+ else:
+ del_on_terminate = 0
+ mapping_opts = ("%s::%s"
+ % (context['volume_id'], del_on_terminate))
+ dev_mapping = {context['device_name']: mapping_opts}
+ else:
+ dev_mapping = None
+
+ netids = context.get('network_id', None)
+ if netids:
+ nics = [{"net-id": netid, "v4-fixed-ip": ""}
+ for netid in netids]
+ else:
+ nics = None
+
+ try:
+ api.nova.server_create(request,
+ context['name'],
+ context['source_id'],
+ context['flavor'],
+ context['keypair_id'],
+ normalize_newlines(custom_script),
+ context['security_group_ids'],
+ dev_mapping,
+ nics=nics,
+ instance_count=int(context['count']))
+ return True
+ except:
+ exceptions.handle(request)
+ return False
diff --git a/openstack_dashboard/dashboards/project/models.py b/openstack_dashboard/dashboards/project/models.py
new file mode 100644
index 000000000..6313a32fa
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/models.py
@@ -0,0 +1,23 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.
+
+"""
+Stub file to work around django bug: https://code.djangoproject.com/ticket/7198
+"""
diff --git a/openstack_dashboard/dashboards/project/networks/__init__.py b/openstack_dashboard/dashboards/project/networks/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/__init__.py
diff --git a/openstack_dashboard/dashboards/project/networks/forms.py b/openstack_dashboard/dashboards/project/networks/forms.py
new file mode 100644
index 000000000..8ba73a6ec
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/forms.py
@@ -0,0 +1,56 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import messages
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class UpdateNetwork(forms.SelfHandlingForm):
+ name = forms.CharField(label=_("Name"), required=False)
+ tenant_id = forms.CharField(widget=forms.HiddenInput)
+ network_id = forms.CharField(label=_("ID"),
+ widget=forms.TextInput(
+ attrs={'readonly': 'readonly'}))
+ failure_url = 'horizon:project:networks:index'
+
+ def handle(self, request, data):
+ try:
+ network = api.quantum.network_modify(request, data['network_id'],
+ name=data['name'])
+ msg = _('Network %s was successfully updated.') % data['name']
+ LOG.debug(msg)
+ messages.success(request, msg)
+ return network
+ except:
+ msg = _('Failed to update network %s') % data['name']
+ LOG.info(msg)
+ redirect = reverse(self.failure_url)
+ exceptions.handle(request, msg, redirect=redirect)
diff --git a/openstack_dashboard/dashboards/project/networks/panel.py b/openstack_dashboard/dashboards/project/networks/panel.py
new file mode 100644
index 000000000..96b472eff
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/panel.py
@@ -0,0 +1,29 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 Networks(horizon.Panel):
+ name = _("Networks")
+ slug = 'networks'
+ permissions = ('openstack.services.network',)
+
+dashboard.Project.register(Networks)
diff --git a/openstack_dashboard/dashboards/project/networks/ports/__init__.py b/openstack_dashboard/dashboards/project/networks/ports/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/ports/__init__.py
diff --git a/openstack_dashboard/dashboards/project/networks/ports/tables.py b/openstack_dashboard/dashboards/project/networks/ports/tables.py
new file mode 100644
index 000000000..1cb6243b7
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/ports/tables.py
@@ -0,0 +1,53 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+
+from django import template
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import tables
+
+
+LOG = logging.getLogger(__name__)
+
+
+def get_fixed_ips(port):
+ template_name = 'project/networks/ports/_port_ips.html'
+ context = {"ips": port.fixed_ips}
+ return template.loader.render_to_string(template_name, context)
+
+
+def get_attached(port):
+ return _('Attached') if port['device_id'] else _('Detached')
+
+
+class PortsTable(tables.DataTable):
+ name = tables.Column("name",
+ verbose_name=_("Name"),
+ link="horizon:project:networks:ports:detail")
+ fixed_ips = tables.Column(get_fixed_ips, verbose_name=_("Fixed IPs"))
+ attached = tables.Column(get_attached, verbose_name=_("Device Attached"))
+ status = tables.Column("status", verbose_name=_("Status"))
+ admin_state = tables.Column("admin_state",
+ verbose_name=_("Admin State"))
+
+ def get_object_display(self, port):
+ return port.id
+
+ class Meta:
+ name = "ports"
+ verbose_name = _("Ports")
diff --git a/openstack_dashboard/dashboards/project/networks/ports/tabs.py b/openstack_dashboard/dashboards/project/networks/ports/tabs.py
new file mode 100644
index 000000000..409a68a48
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/ports/tabs.py
@@ -0,0 +1,49 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tabs
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class OverviewTab(tabs.Tab):
+ name = _("Overview")
+ slug = "overview"
+ template_name = "project/networks/ports/_detail_overview.html"
+
+ def get_context_data(self, request):
+ port_id = self.tab_group.kwargs['port_id']
+ try:
+ port = api.quantum.port_get(self.request, port_id)
+ except:
+ redirect = reverse('horizon:project:networks:index')
+ msg = _('Unable to retrieve port details.')
+ exceptions.handle(request, msg, redirect=redirect)
+ return {'port': port}
+
+
+class PortDetailTabs(tabs.TabGroup):
+ slug = "port_details"
+ tabs = (OverviewTab,)
diff --git a/openstack_dashboard/dashboards/project/networks/ports/urls.py b/openstack_dashboard/dashboards/project/networks/ports/urls.py
new file mode 100644
index 000000000..7dd711a3b
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/ports/urls.py
@@ -0,0 +1,28 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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.defaults import patterns, url
+
+from .views import DetailView
+
+
+PORTS = r'^(?P<port_id>[^/]+)/%s$'
+VIEW_MOD = 'openstack_dashboard.dashboards.project.networks.ports.views'
+
+
+urlpatterns = patterns(VIEW_MOD,
+ url(PORTS % 'detail', DetailView.as_view(), name='detail')
+)
diff --git a/openstack_dashboard/dashboards/project/networks/ports/views.py b/openstack_dashboard/dashboards/project/networks/ports/views.py
new file mode 100644
index 000000000..14f361440
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/ports/views.py
@@ -0,0 +1,24 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 horizon import tabs
+
+from .tabs import PortDetailTabs
+
+
+class DetailView(tabs.TabView):
+ tab_group_class = PortDetailTabs
+ template_name = 'project/networks/ports/detail.html'
diff --git a/openstack_dashboard/dashboards/project/networks/subnets/__init__.py b/openstack_dashboard/dashboards/project/networks/subnets/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/subnets/__init__.py
diff --git a/openstack_dashboard/dashboards/project/networks/subnets/forms.py b/openstack_dashboard/dashboards/project/networks/subnets/forms.py
new file mode 100644
index 000000000..c03febb59
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/subnets/forms.py
@@ -0,0 +1,139 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+import netaddr
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import forms
+from horizon import messages
+from horizon import exceptions
+from horizon.utils import fields
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateSubnet(forms.SelfHandlingForm):
+ network_name = forms.CharField(label=_("Network Name"),
+ required=False,
+ widget=forms.TextInput(
+ attrs={'readonly': 'readonly'}))
+ network_id = forms.CharField(label=_("Network ID"),
+ widget=forms.TextInput(
+ attrs={'readonly': 'readonly'}))
+ name = forms.CharField(max_length=255,
+ label=_("Name"),
+ required=False)
+ cidr = fields.IPField(label=_("Network Address"),
+ required=True,
+ initial="",
+ help_text=_("Network address in CIDR format "
+ "(e.g. 192.168.0.0/24)"),
+ version=fields.IPv4 | fields.IPv6,
+ mask=True)
+ ip_version = forms.ChoiceField(choices=[(4, 'IPv4'), (6, 'IPv6')],
+ label=_("IP Version"))
+ gateway_ip = fields.IPField(label=_("Gateway IP"),
+ required=False,
+ initial="",
+ help_text=_("IP address of Gateway "
+ "(e.g. 192.168.0.1)"),
+ version=fields.IPv4 | fields.IPv6,
+ mask=False)
+ failure_url = 'horizon:project:networks:detail'
+
+ def clean(self):
+ cleaned_data = super(CreateSubnet, self).clean()
+ cidr = cleaned_data.get('cidr')
+ ip_version = int(cleaned_data.get('ip_version'))
+ gateway_ip = cleaned_data.get('gateway_ip')
+ if cidr:
+ if netaddr.IPNetwork(cidr).version is not ip_version:
+ msg = _('Network Address and IP version are inconsistent.')
+ raise forms.ValidationError(msg)
+ if gateway_ip:
+ if netaddr.IPAddress(gateway_ip).version is not ip_version:
+ msg = _('Gateway IP and IP version are inconsistent.')
+ raise forms.ValidationError(msg)
+ return cleaned_data
+
+ def handle(self, request, data):
+ try:
+ LOG.debug('params = %s' % data)
+ data['ip_version'] = int(data['ip_version'])
+ if not data['gateway_ip']:
+ del data['gateway_ip']
+ subnet = api.quantum.subnet_create(request, **data)
+ msg = _('Subnet %s was successfully created.') % data['cidr']
+ LOG.debug(msg)
+ messages.success(request, msg)
+ return subnet
+ except Exception:
+ msg = _('Failed to create subnet %s') % data['cidr']
+ LOG.info(msg)
+ redirect = reverse(self.failure_url, args=[data['network_id']])
+ exceptions.handle(request, msg, redirect=redirect)
+
+
+class UpdateSubnet(forms.SelfHandlingForm):
+ network_id = forms.CharField(widget=forms.HiddenInput())
+ subnet_id = forms.CharField(widget=forms.HiddenInput())
+ cidr = forms.CharField(widget=forms.HiddenInput())
+ ip_version = forms.CharField(widget=forms.HiddenInput())
+ name = forms.CharField(max_length=255,
+ label=_("Name"),
+ required=False)
+ gateway_ip = fields.IPField(label=_("Gateway IP"),
+ required=True,
+ initial="",
+ help_text=_("IP address of Gateway "
+ "(e.g. 192.168.0.1)"),
+ version=fields.IPv4 | fields.IPv6,
+ mask=False)
+ failure_url = 'horizon:project:networks:detail'
+
+ def clean(self):
+ cleaned_data = super(UpdateSubnet, self).clean()
+ ip_version = int(cleaned_data.get('ip_version'))
+ gateway_ip = cleaned_data.get('gateway_ip')
+ if gateway_ip:
+ if netaddr.IPAddress(gateway_ip).version is not ip_version:
+ msg = _('Gateway IP and IP version are inconsistent.')
+ raise forms.ValidationError(msg)
+ return cleaned_data
+
+ def handle(self, request, data):
+ try:
+ LOG.debug('params = %s' % data)
+ params = {'name': data['name']}
+ params['gateway_ip'] = data['gateway_ip']
+ subnet = api.quantum.subnet_modify(request, data['subnet_id'],
+ name=data['name'],
+ gateway_ip=data['gateway_ip'])
+ msg = _('Subnet %s was successfully updated.') % data['cidr']
+ LOG.debug(msg)
+ messages.success(request, msg)
+ return subnet
+ except Exception:
+ msg = _('Failed to update subnet %s') % data['cidr']
+ LOG.info(msg)
+ redirect = reverse(self.failure_url, args=[data['network_id']])
+ exceptions.handle(request, msg, redirect=redirect)
diff --git a/openstack_dashboard/dashboards/project/networks/subnets/tables.py b/openstack_dashboard/dashboards/project/networks/subnets/tables.py
new file mode 100644
index 000000000..a0ba72ff8
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/subnets/tables.py
@@ -0,0 +1,106 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse, reverse_lazy
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tables
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CheckNetworkEditable(object):
+ """Mixin class to determine the specified network is editable."""
+
+ def allowed(self, request, datum=None):
+ # Only administrator is allowed to create and manage subnets
+ # on shared networks.
+ network = self.table._get_network()
+ if network.shared:
+ return False
+ return True
+
+
+class DeleteSubnet(CheckNetworkEditable, tables.DeleteAction):
+ data_type_singular = _("Subnet")
+ data_type_plural = _("Subnets")
+
+ def delete(self, request, obj_id):
+ try:
+ api.quantum.subnet_delete(request, obj_id)
+ except:
+ msg = _('Failed to delete subnet %s') % obj_id
+ LOG.info(msg)
+ network_id = self.table.kwargs['network_id']
+ redirect = reverse('horizon:project:networks:detail',
+ args=[network_id])
+ exceptions.handle(request, msg, redirect=redirect)
+
+
+class CreateSubnet(CheckNetworkEditable, tables.LinkAction):
+ name = "create"
+ verbose_name = _("Create Subnet")
+ url = "horizon:project:networks:addsubnet"
+ classes = ("ajax-modal", "btn-create")
+
+ def get_link_url(self, datum=None):
+ network_id = self.table.kwargs['network_id']
+ return reverse(self.url, args=(network_id,))
+
+
+class UpdateSubnet(CheckNetworkEditable, tables.LinkAction):
+ name = "update"
+ verbose_name = _("Edit Subnet")
+ url = "horizon:project:networks:editsubnet"
+ classes = ("ajax-modal", "btn-edit")
+
+ def get_link_url(self, subnet):
+ network_id = self.table.kwargs['network_id']
+ return reverse(self.url, args=(network_id, subnet.id))
+
+
+class SubnetsTable(tables.DataTable):
+ name = tables.Column("name", verbose_name=_("Name"),
+ link='horizon:project:networks:subnets:detail')
+ cidr = tables.Column("cidr", verbose_name=_("Network Address"))
+ ip_version = tables.Column("ipver_str", verbose_name=_("IP Version"))
+ gateway_ip = tables.Column("gateway_ip", verbose_name=_("Gateway IP"))
+ failure_url = reverse_lazy('horizon:project:networks:index')
+
+ def _get_network(self):
+ if not hasattr(self, "_network"):
+ try:
+ network_id = self.kwargs['network_id']
+ network = api.quantum.network_get(self.request, network_id)
+ network.set_id_as_name_if_empty(length=0)
+ except:
+ msg = _('Unable to retrieve details for network "%s".') \
+ % (network_id)
+ exceptions.handle(self.request, msg, redirect=self.failure_url)
+ self._network = network
+ return self._network
+
+ class Meta:
+ name = "subnets"
+ verbose_name = _("Subnets")
+ table_actions = (CreateSubnet, DeleteSubnet)
+ row_actions = (UpdateSubnet, DeleteSubnet)
diff --git a/openstack_dashboard/dashboards/project/networks/subnets/tabs.py b/openstack_dashboard/dashboards/project/networks/subnets/tabs.py
new file mode 100644
index 000000000..36034879c
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/subnets/tabs.py
@@ -0,0 +1,49 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tabs
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class OverviewTab(tabs.Tab):
+ name = _("Overview")
+ slug = "overview"
+ template_name = "project/networks/subnets/_detail_overview.html"
+
+ def get_context_data(self, request):
+ subnet_id = self.tab_group.kwargs['subnet_id']
+ try:
+ subnet = api.quantum.subnet_get(self.request, subnet_id)
+ except:
+ redirect = reverse('horizon:project:networks:index')
+ msg = _('Unable to retrieve subnet details.')
+ exceptions.handle(request, msg, redirect=redirect)
+ return {'subnet': subnet}
+
+
+class SubnetDetailTabs(tabs.TabGroup):
+ slug = "subnet_details"
+ tabs = (OverviewTab,)
diff --git a/openstack_dashboard/dashboards/project/networks/subnets/urls.py b/openstack_dashboard/dashboards/project/networks/subnets/urls.py
new file mode 100644
index 000000000..a83e783b6
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/subnets/urls.py
@@ -0,0 +1,28 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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.defaults import patterns, url
+
+from .views import DetailView
+
+
+SUBNETS = r'^(?P<subnet_id>[^/]+)/%s$'
+VIEW_MOD = 'openstack_dashboard.dashboards.project.networks.subnets.views'
+
+
+urlpatterns = patterns(VIEW_MOD,
+ url(SUBNETS % 'detail', DetailView.as_view(), name='detail')
+)
diff --git a/openstack_dashboard/dashboards/project/networks/subnets/views.py b/openstack_dashboard/dashboards/project/networks/subnets/views.py
new file mode 100644
index 000000000..52d308023
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/subnets/views.py
@@ -0,0 +1,111 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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.
+
+"""
+Views for managing Quantum Subnets.
+"""
+import logging
+
+from django.core.urlresolvers import reverse_lazy, reverse
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import forms
+from horizon import exceptions
+from horizon import tabs
+
+from openstack_dashboard import api
+from .forms import CreateSubnet, UpdateSubnet
+from .tabs import SubnetDetailTabs
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateView(forms.ModalFormView):
+ form_class = CreateSubnet
+ template_name = 'project/networks/subnets/create.html'
+ success_url = 'horizon:project:networks:detail'
+
+ def get_success_url(self):
+ return reverse(self.success_url,
+ args=(self.kwargs['network_id'],))
+
+ def get_object(self):
+ if not hasattr(self, "_object"):
+ try:
+ network_id = self.kwargs["network_id"]
+ self._object = api.quantum.network_get(self.request,
+ network_id)
+ except:
+ redirect = reverse('horizon:project:networks:index')
+ msg = _("Unable to retrieve network.")
+ exceptions.handle(self.request, msg, redirect=redirect)
+ return self._object
+
+ def get_context_data(self, **kwargs):
+ context = super(CreateView, self).get_context_data(**kwargs)
+ context['network'] = self.get_object()
+ return context
+
+ def get_initial(self):
+ network = self.get_object()
+ return {"network_id": self.kwargs['network_id'],
+ "network_name": network.name}
+
+
+class UpdateView(forms.ModalFormView):
+ form_class = UpdateSubnet
+ template_name = 'project/networks/subnets/update.html'
+ context_object_name = 'subnet'
+ success_url = reverse_lazy('horizon:project:networks:detail')
+
+ def get_success_url(self):
+ return reverse('horizon:project:networks:detail',
+ args=(self.kwargs['network_id'],))
+
+ def _get_object(self, *args, **kwargs):
+ if not hasattr(self, "_object"):
+ subnet_id = self.kwargs['subnet_id']
+ try:
+ self._object = api.quantum.subnet_get(self.request, subnet_id)
+ except:
+ redirect = reverse("horizon:project:networks:index")
+ msg = _('Unable to retrieve subnet details')
+ exceptions.handle(self.request, msg, redirect=redirect)
+ return self._object
+
+ def get_context_data(self, **kwargs):
+ context = super(UpdateView, self).get_context_data(**kwargs)
+ subnet = self._get_object()
+ context['subnet_id'] = subnet.id
+ context['network_id'] = subnet.network_id
+ context['cidr'] = subnet.cidr
+ context['ip_version'] = subnet.ipver_str
+ return context
+
+ def get_initial(self):
+ subnet = self._get_object()
+ return {'network_id': self.kwargs['network_id'],
+ 'subnet_id': subnet['id'],
+ 'cidr': subnet['cidr'],
+ 'ip_version': subnet['ip_version'],
+ 'name': subnet['name'],
+ 'gateway_ip': subnet['gateway_ip']}
+
+
+class DetailView(tabs.TabView):
+ tab_group_class = SubnetDetailTabs
+ template_name = 'project/networks/subnets/detail.html'
diff --git a/openstack_dashboard/dashboards/project/networks/tables.py b/openstack_dashboard/dashboards/project/networks/tables.py
new file mode 100644
index 000000000..bd1345ae5
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/tables.py
@@ -0,0 +1,108 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+
+from django import template
+from django.core.urlresolvers import reverse
+from django.template import defaultfilters as filters
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tables
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CheckNetworkEditable(object):
+ """Mixin class to determine the specified network is editable."""
+
+ def allowed(self, request, datum=None):
+ # Only administrator is allowed to create and manage shared networks.
+ if datum and datum.shared:
+ return False
+ return True
+
+
+class DeleteNetwork(CheckNetworkEditable, tables.DeleteAction):
+ data_type_singular = _("Network")
+ data_type_plural = _("Networks")
+
+ def delete(self, request, network_id):
+ try:
+ # Retrieve existing subnets belonging to the network.
+ subnets = api.quantum.subnet_list(request, network_id=network_id)
+ LOG.debug('Network %s has subnets: %s' %
+ (network_id, [s.id for s in subnets]))
+ for s in subnets:
+ api.quantum.subnet_delete(request, s.id)
+ LOG.debug('Deleted subnet %s' % s.id)
+
+ api.quantum.network_delete(request, network_id)
+ LOG.debug('Deleted network %s successfully' % network_id)
+ except:
+ msg = _('Failed to delete network %s') % network_id
+ LOG.info(msg)
+ redirect = reverse("horizon:project:networks:index")
+ exceptions.handle(request, msg, redirect=redirect)
+
+
+class CreateNetwork(tables.LinkAction):
+ name = "create"
+ verbose_name = _("Create Network")
+ url = "horizon:project:networks:create"
+ classes = ("ajax-modal", "btn-create")
+
+
+class EditNetwork(CheckNetworkEditable, tables.LinkAction):
+ name = "update"
+ verbose_name = _("Edit Network")
+ url = "horizon:project:networks:update"
+ classes = ("ajax-modal", "btn-edit")
+
+
+class CreateSubnet(CheckNetworkEditable, tables.LinkAction):
+ name = "subnet"
+ verbose_name = _("Add Subnet")
+ url = "horizon:project:networks:addsubnet"
+ classes = ("ajax-modal", "btn-create")
+
+
+def get_subnets(network):
+ template_name = 'project/networks/_network_ips.html'
+ context = {"subnets": network.subnets}
+ return template.loader.render_to_string(template_name, context)
+
+
+class NetworksTable(tables.DataTable):
+ name = tables.Column("name",
+ verbose_name=_("Name"),
+ link='horizon:project:networks:detail')
+ subnets = tables.Column(get_subnets,
+ verbose_name=_("Subnets Associated"),)
+ shared = tables.Column("shared", verbose_name=_("Shared"),
+ filters=(filters.yesno, filters.capfirst))
+ status = tables.Column("status", verbose_name=_("Status"))
+ admin_state = tables.Column("admin_state",
+ verbose_name=_("Admin State"))
+
+ class Meta:
+ name = "networks"
+ verbose_name = _("Networks")
+ table_actions = (CreateNetwork, DeleteNetwork)
+ row_actions = (EditNetwork, CreateSubnet, DeleteNetwork)
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/_create.html b/openstack_dashboard/dashboards/project/networks/templates/networks/_create.html
new file mode 100644
index 000000000..aeb53650b
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/_create.html
@@ -0,0 +1,24 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}create_network_form{% endblock %}
+{% block form_action %}{% url horizon:project:networks:create %}{% endblock %}
+
+{% block modal-header %}{% trans "Create Network" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "Select a name for your network."%}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Network" %}" />
+ <a href="{% url horizon:project:networks:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/_detail_overview.html b/openstack_dashboard/dashboards/project/networks/templates/networks/_detail_overview.html
new file mode 100644
index 000000000..b64341fb5
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/_detail_overview.html
@@ -0,0 +1,20 @@
+{% load i18n sizeformat %}
+
+<h3>{% trans "Network Overview" %}</h3>
+
+<div class="info detail">
+ <dl>
+ <dt>{% trans "Name" %}</dt>
+ <dd>{{ network.name|default:"None" }}</dd>
+ <dt>{% trans "ID" %}</dt>
+ <dd>{{ network.id|default:"None" }}</dd>
+ <dt>{% trans "Project ID" %}</dt>
+ <dd>{{ network.tenant_id|default:"-" }}</dd>
+ <dt>{% trans "Status" %}</dt>
+ <dd>{{ network.status|default:"Unknown" }}</dd>
+ <dt>{% trans "Admin State" %}</dt>
+ <dd>{{ network.admin_state|default:"Unknown" }}</dd>
+ <dt>{% trans "Shared" %}</dt>
+ <dd>{{ network.shared|yesno|capfirst }}</dd>
+ </dl>
+</div>
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/_network_ips.html b/openstack_dashboard/dashboards/project/networks/templates/networks/_network_ips.html
new file mode 100644
index 000000000..a80e74795
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/_network_ips.html
@@ -0,0 +1,10 @@
+{% for subnet in subnets %}
+<ul>
+ <li>
+ {% if subnet.name|length > 0 %}
+ <b>{{ subnet.name }}</b>
+ {% endif %}
+ {{ subnet.cidr }}
+ </li>
+</ul>
+{% endfor %}
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/_update.html b/openstack_dashboard/dashboards/project/networks/templates/networks/_update.html
new file mode 100644
index 000000000..9638dff87
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/_update.html
@@ -0,0 +1,24 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}update_network_form{% endblock %}
+{% block form_action %}{% url horizon:project:networks:update network_id %}{% endblock %}
+
+{% block modal-header %}{% trans "Edit Network" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description:" %}</h3>
+ <p>{% trans "You may update the editable properties of your network here." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Save Changes" %}" />
+ <a href="{% url horizon:project:networks:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/create.html b/openstack_dashboard/dashboards/project/networks/templates/networks/create.html
new file mode 100644
index 000000000..5a9d7da31
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/create.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Create Network" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Create Network") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include "horizon/common/_workflow.html" %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/detail.html b/openstack_dashboard/dashboards/project/networks/templates/networks/detail.html
new file mode 100644
index 000000000..d6773feb0
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/detail.html
@@ -0,0 +1,18 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Network Detail"%}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Network Detail: ")|add:network.name %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include "project/networks/_detail_overview.html" %}
+ <hr>
+ <div id="subnets">
+ {{ subnets_table.render }}
+ </div>
+ <div id="ports">
+ {{ ports_table.render }}
+ </div>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/index.html b/openstack_dashboard/dashboards/project/networks/templates/networks/index.html
new file mode 100644
index 000000000..d458220ab
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/index.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Networks" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Networks") %}
+{% endblock page_header %}
+
+{% block main %}
+ {{ table.render }}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/ports/_detail_overview.html b/openstack_dashboard/dashboards/project/networks/templates/networks/ports/_detail_overview.html
new file mode 100644
index 000000000..401a5db69
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/ports/_detail_overview.html
@@ -0,0 +1,41 @@
+{% load i18n sizeformat %}
+
+<h3>{% trans "Port Overview" %}</h3>
+
+<div class="info row-fluid detail">
+ <h4>{% trans "Port" %}</h4>
+ <hr class="header_rule">
+ <dl>
+ <dt>{% trans "Name" %}</dt>
+ <dd>{{ port.name|default:"None" }}</dd>
+ <dt>{% trans "ID" %}</dt>
+ <dd>{{ port.id|default:"None" }}</dd>
+ <dt>{% trans "Network ID" %}</dt>
+ <dd>{{ port.network_id|default:"None" }}</dd>
+ <dt>{% trans "Project ID" %}</dt>
+ <dd>{{ port.tenant_id|default:"-" }}</dd>
+ <dt>{% trans "Fixed IP" %}</dt>
+ <dd>
+ {% if port.fixed_ips.items|length > 1 %}
+ {% for ip in port.fixed_ips %}
+ <b>{% trans "IP address:" %}</b> {{ ip.ip_address }},
+ <b>{% trans "Subnet ID" %}</b> {{ ip.subnet_id }}<br>
+ {% endfor %}
+ {% else %}
+ "None"
+ {% endif %}
+ </dd>
+ <dt>{% trans "Mac Address" %}</dt>
+ <dd>{{ port.mac_address|default:"None" }}</dd>
+ <dt>{% trans "Status" %}</dt>
+ <dd>{{ port.status|default:"None" }}</dd>
+ <dt>{% trans "Admin State" %}</dt>
+ <dd>{{ port.admin_state|default:"None" }}</dd>
+ <dt>{% trans "Device ID" %}</dt>
+ {% if port.device_id|length > 1 %}
+ <dd>{{ port.device_id }}</dd>
+ {% else %}
+ <dd>No attached device</dd>
+ {% endif %}
+ </dl>
+</div>
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/ports/_port_ips.html b/openstack_dashboard/dashboards/project/networks/templates/networks/ports/_port_ips.html
new file mode 100644
index 000000000..bfd5ea9f1
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/ports/_port_ips.html
@@ -0,0 +1,7 @@
+{% for ip in ips %}
+<ul>
+ <li>
+ {{ ip.ip_address }}
+ </li>
+</ul>
+{% endfor %}
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/ports/detail.html b/openstack_dashboard/dashboards/project/networks/templates/networks/ports/detail.html
new file mode 100644
index 000000000..634c6d67e
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/ports/detail.html
@@ -0,0 +1,15 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Port Detail"%}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Port Detail") %}
+{% endblock page_header %}
+
+{% block main %}
+<div id="row-fluid">
+ <div class="span12">
+ {{ tab_group.render }}
+ </div>
+</div>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/_create.html b/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/_create.html
new file mode 100644
index 000000000..cd4ebbc1c
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/_create.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}create_subnet_form{% endblock %}
+{% block form_action %}{% url horizon:project:networks:addsubnet network.id %}
+{% endblock %}
+
+{% block modal-header %}{% trans "Create Subnet" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "You can create a subnet for the network. Any network address can be specified unless the network address does not overlap other subnets in the network." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Subnet" %}" />
+ <a href="{% url horizon:project:networks:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/_detail_overview.html b/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/_detail_overview.html
new file mode 100644
index 000000000..4c09fde09
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/_detail_overview.html
@@ -0,0 +1,29 @@
+{% load i18n sizeformat %}
+
+<h3>{% trans "Subnet Overview" %}</h3>
+
+<div class="info row-fluid detail">
+ <h4>{% trans "Subnet" %}</h4>
+ <hr class="header_rule">
+ <dl>
+ <dt>{% trans "Name" %}</dt>
+ <dd>{{ subnet.name|default:"None" }}</dd>
+ <dt>{% trans "ID" %}</dt>
+ <dd>{{ subnet.id|default:"None" }}</dd>
+ <dt>{% trans "Network ID" %}</dt>
+ <dd>{{ subnet.network_id|default:"None" }}</dd>
+ <dt>{% trans "CIDR" %}</dt>
+ <dd>{{ subnet.cidr|default:"None" }}</dd>
+ <dt>{% trans "IP version" %}</dt>
+ <dd>{{ subnet.ipver_str|default:"-" }}</dd>
+ <dt>{% trans "Gateway IP" %}</dt>
+ <dd>{{ subnet.gateway_ip|default:"-" }}</dd>
+ <dt>{% trans "IP allocation pool" %}</dt>
+ <dd>
+ {% for pool in subnet.allocation_pools %}
+ {% trans "Start" %} {{ pool.start }}
+ {% trans " - End" %} {{ pool.end }}<br>
+ {% endfor %}
+ </dd>
+ </dl>
+</div>
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/_update.html b/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/_update.html
new file mode 100644
index 000000000..f74b5e280
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/_update.html
@@ -0,0 +1,33 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}update_subnet_form{% endblock %}
+{% block form_action %}{% url horizon:project:networks:editsubnet network_id subnet_id %}{% endblock %}
+
+{% block modal-header %}{% trans "Edit Subnet" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <dl>
+ <dt>{% trans "ID" %}</dt>
+ <dd>{{ subnet_id }}</dd>
+ <dt>{% trans "Network Address" %}</dt>
+ <dd>{{ cidr }}</dd>
+ <dt>{% trans "IP version" %}</dt>
+ <dd>{{ ip_version }}</dd>
+ </dl>
+ <hr>
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description:" %}</h3>
+ <p>{% trans "You may update the editable properties of your subnet here." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Save Changes" %}" />
+ <a href="{% url horizon:project:networks:detail network_id %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/create.html b/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/create.html
new file mode 100644
index 000000000..7a614b1b8
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/create.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Create Subnet" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Create Subnet") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include "project/networks/subnets/_create.html" %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/detail.html b/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/detail.html
new file mode 100644
index 000000000..c4e35bd07
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/detail.html
@@ -0,0 +1,15 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Subnet Detail"%}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Subnet Detail") %}
+{% endblock page_header %}
+
+{% block main %}
+<div id="row-fluid">
+ <div class="span12">
+ {{ tab_group.render }}
+ </div>
+</div>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/index.html b/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/index.html
new file mode 100644
index 000000000..833399a22
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/index.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Network" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Network") %}
+{% endblock page_header %}
+
+{% block main %}
+ {{ table.render }}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/update.html b/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/update.html
new file mode 100644
index 000000000..1d74569d6
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/subnets/update.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Update Subnet" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Update Subnet") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'project/networks/subnets/_update.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/networks/templates/networks/update.html b/openstack_dashboard/dashboards/project/networks/templates/networks/update.html
new file mode 100644
index 000000000..07f5993f7
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/templates/networks/update.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Update Network" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Update Network") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'project/networks/_update.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/networks/tests.py b/openstack_dashboard/dashboards/project/networks/tests.py
new file mode 100644
index 000000000..a9e246929
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/tests.py
@@ -0,0 +1,782 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 import http
+from django.core.urlresolvers import reverse
+from django.utils.html import escape
+
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+from .workflows import CreateNetwork
+
+
+INDEX_URL = reverse('horizon:project:networks:index')
+
+
+class NetworkTests(test.TestCase):
+ @test.create_stubs({api.quantum: ('network_list',)})
+ def test_index(self):
+ api.quantum.network_list(
+ IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ shared=False).AndReturn(self.networks.list())
+ api.quantum.network_list(
+ IsA(http.HttpRequest),
+ shared=True).AndReturn([])
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(INDEX_URL)
+
+ self.assertTemplateUsed(res, 'project/networks/index.html')
+ networks = res.context['networks_table'].data
+ self.assertItemsEqual(networks, self.networks.list())
+
+ @test.create_stubs({api.quantum: ('network_list',)})
+ def test_index_network_list_exception(self):
+ api.quantum.network_list(
+ IsA(http.HttpRequest),
+ tenant_id=self.tenant.id,
+ shared=False).AndRaise(self.exceptions.quantum)
+ self.mox.ReplayAll()
+
+ res = self.client.get(INDEX_URL)
+
+ self.assertTemplateUsed(res, 'project/networks/index.html')
+ self.assertEqual(len(res.context['networks_table'].data), 0)
+ self.assertMessageCount(res, error=1)
+
+ @test.create_stubs({api.quantum: ('network_get',
+ 'subnet_list',
+ 'port_list',)})
+ def test_network_detail(self):
+ network_id = self.networks.first().id
+ api.quantum.network_get(IsA(http.HttpRequest), network_id)\
+ .AndReturn(self.networks.first())
+ api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.subnets.first()])
+ api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.ports.first()])
+ api.quantum.network_get(IsA(http.HttpRequest), network_id)\
+ .AndReturn(self.networks.first())
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:project:networks:detail',
+ args=[network_id]))
+
+ self.assertTemplateUsed(res, 'project/networks/detail.html')
+ subnets = res.context['subnets_table'].data
+ ports = res.context['ports_table'].data
+ self.assertItemsEqual(subnets, [self.subnets.first()])
+ self.assertItemsEqual(ports, [self.ports.first()])
+
+ @test.create_stubs({api.quantum: ('network_get',
+ 'subnet_list',
+ 'port_list',)})
+ def test_network_detail_network_exception(self):
+ network_id = self.networks.first().id
+ api.quantum.network_get(IsA(http.HttpRequest), network_id)\
+ .AndRaise(self.exceptions.quantum)
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:networks:detail', args=[network_id])
+ res = self.client.get(url)
+
+ redir_url = INDEX_URL
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('network_get',
+ 'subnet_list',
+ 'port_list',)})
+ def test_network_detail_subnet_exception(self):
+ network_id = self.networks.first().id
+ api.quantum.network_get(IsA(http.HttpRequest), network_id).\
+ AndReturn(self.networks.first())
+ api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id).\
+ AndRaise(self.exceptions.quantum)
+ api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id).\
+ AndReturn([self.ports.first()])
+ # Called from SubnetTable
+ api.quantum.network_get(IsA(http.HttpRequest), network_id).\
+ AndReturn(self.networks.first())
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:project:networks:detail',
+ args=[network_id]))
+
+ self.assertTemplateUsed(res, 'project/networks/detail.html')
+ subnets = res.context['subnets_table'].data
+ ports = res.context['ports_table'].data
+ self.assertEqual(len(subnets), 0)
+ self.assertItemsEqual(ports, [self.ports.first()])
+
+ @test.create_stubs({api.quantum: ('network_get',
+ 'subnet_list',
+ 'port_list',)})
+ def test_network_detail_port_exception(self):
+ network_id = self.networks.first().id
+ api.quantum.network_get(IsA(http.HttpRequest), network_id).\
+ AndReturn(self.networks.first())
+ api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id).\
+ AndReturn([self.subnets.first()])
+ api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id).\
+ AndRaise(self.exceptions.quantum)
+ # Called from SubnetTable
+ api.quantum.network_get(IsA(http.HttpRequest), network_id).\
+ AndReturn(self.networks.first())
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:project:networks:detail',
+ args=[network_id]))
+
+ self.assertTemplateUsed(res, 'project/networks/detail.html')
+ subnets = res.context['subnets_table'].data
+ ports = res.context['ports_table'].data
+ self.assertItemsEqual(subnets, [self.subnets.first()])
+ self.assertEqual(len(ports), 0)
+
+ def test_network_create_get(self):
+ # no api methods are called.
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:networks:create')
+ res = self.client.get(url)
+
+ workflow = res.context['workflow']
+ self.assertTemplateUsed(res, 'project/networks/create.html')
+ self.assertEqual(workflow.name, CreateNetwork.name)
+ expected_objs = ['<CreateNetworkInfo: createnetworkinfoaction>',
+ '<CreateSubnetInfo: createsubnetinfoaction>']
+ self.assertQuerysetEqual(workflow.steps, expected_objs)
+
+ @test.create_stubs({api.quantum: ('network_create',)})
+ def test_network_create_post(self):
+ network = self.networks.first()
+ api.quantum.network_create(IsA(http.HttpRequest), name=network.name)\
+ .AndReturn(network)
+ self.mox.ReplayAll()
+
+ form_data = {'net_name': network.name,
+ 'with_subnet': False,
+ 'subnet_name': '',
+ 'cidr': '',
+ 'ip_version': 4,
+ 'gateway_ip': ''}
+ url = reverse('horizon:project:networks:create')
+ res = self.client.post(url, form_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('network_create',
+ 'subnet_create',)})
+ def test_network_create_post_with_subnet(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ api.quantum.network_create(IsA(http.HttpRequest), name=network.name)\
+ .AndReturn(network)
+ api.quantum.subnet_create(IsA(http.HttpRequest),
+ network_id=network.id,
+ name=subnet.name,
+ cidr=subnet.cidr,
+ ip_version=subnet.ip_version,
+ gateway_ip=subnet.gateway_ip)\
+ .AndReturn(subnet)
+ self.mox.ReplayAll()
+
+ form_data = {'net_name': network.name,
+ 'with_subnet': True,
+ 'subnet_name': subnet.name,
+ 'cidr': subnet.cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': subnet.gateway_ip}
+ url = reverse('horizon:project:networks:create')
+ res = self.client.post(url, form_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('network_create',)})
+ def test_network_create_post_network_exception(self):
+ network = self.networks.first()
+ api.quantum.network_create(IsA(http.HttpRequest), name=network.name)\
+ .AndRaise(self.exceptions.quantum)
+ self.mox.ReplayAll()
+
+ form_data = {'net_name': network.name,
+ 'with_subnet': False,
+ 'subnet_name': '',
+ 'cidr': '',
+ 'ip_version': 4,
+ 'gateway_ip': ''}
+ url = reverse('horizon:project:networks:create')
+ res = self.client.post(url, form_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('network_create',)})
+ def test_network_create_post_with_subnet_network_exception(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ api.quantum.network_create(IsA(http.HttpRequest), name=network.name)\
+ .AndRaise(self.exceptions.quantum)
+ self.mox.ReplayAll()
+
+ form_data = {'net_name': network.name,
+ 'with_subnet': True,
+ 'subnet_name': subnet.name,
+ 'cidr': subnet.cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': subnet.gateway_ip}
+ url = reverse('horizon:project:networks:create')
+ res = self.client.post(url, form_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('network_create',
+ 'subnet_create',)})
+ def test_network_create_post_with_subnet_subnet_exception(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ api.quantum.network_create(IsA(http.HttpRequest), name=network.name)\
+ .AndReturn(network)
+ api.quantum.subnet_create(IsA(http.HttpRequest),
+ network_id=network.id,
+ name=subnet.name,
+ cidr=subnet.cidr,
+ ip_version=subnet.ip_version,
+ gateway_ip=subnet.gateway_ip)\
+ .AndRaise(self.exceptions.quantum)
+ self.mox.ReplayAll()
+
+ form_data = {'net_name': network.name,
+ 'with_subnet': True,
+ 'subnet_name': subnet.name,
+ 'cidr': subnet.cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': subnet.gateway_ip}
+ url = reverse('horizon:project:networks:create')
+ res = self.client.post(url, form_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ def test_network_create_post_with_subnet_nocidr(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ self.mox.ReplayAll()
+
+ form_data = {'net_name': network.name,
+ 'with_subnet': True,
+ 'subnet_name': subnet.name,
+ 'cidr': '',
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': subnet.gateway_ip}
+ url = reverse('horizon:project:networks:create')
+ res = self.client.post(url, form_data)
+
+ self.assertContains(res, escape('Specify "Network Address" or '
+ 'clear "Create Subnet" checkbox.'))
+
+ def test_network_create_post_with_subnet_cidr_inconsistent(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ self.mox.ReplayAll()
+
+ # dummy IPv6 address
+ cidr = '2001:0DB8:0:CD30:123:4567:89AB:CDEF/60'
+ form_data = {'net_name': network.name,
+ 'with_subnet': True,
+ 'subnet_name': subnet.name,
+ 'cidr': cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': subnet.gateway_ip}
+ url = reverse('horizon:project:networks:create')
+ res = self.client.post(url, form_data)
+
+ expected_msg = 'Network Address and IP version are inconsistent.'
+ self.assertContains(res, expected_msg)
+
+ def test_network_create_post_with_subnet_gw_inconsistent(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ self.mox.ReplayAll()
+
+ # dummy IPv6 address
+ gateway_ip = '2001:0DB8:0:CD30:123:4567:89AB:CDEF'
+ form_data = {'net_name': network.name,
+ 'with_subnet': True,
+ 'subnet_name': subnet.name,
+ 'cidr': subnet.cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': gateway_ip}
+ url = reverse('horizon:project:networks:create')
+ res = self.client.post(url, form_data)
+
+ self.assertContains(res, 'Gateway IP and IP version are inconsistent.')
+
+ @test.create_stubs({api.quantum: ('network_get',)})
+ def test_network_update_get(self):
+ network = self.networks.first()
+ api.quantum.network_get(IsA(http.HttpRequest), network.id)\
+ .AndReturn(network)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:networks:update', args=[network.id])
+ res = self.client.get(url)
+
+ self.assertTemplateUsed(res, 'project/networks/update.html')
+
+ @test.create_stubs({api.quantum: ('network_get',)})
+ def test_network_update_get_exception(self):
+ network = self.networks.first()
+ api.quantum.network_get(IsA(http.HttpRequest), network.id)\
+ .AndRaise(self.exceptions.quantum)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:networks:update', args=[network.id])
+ res = self.client.get(url)
+
+ redir_url = INDEX_URL
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('network_modify',
+ 'network_get',)})
+ def test_network_update_post(self):
+ network = self.networks.first()
+ api.quantum.network_modify(IsA(http.HttpRequest), network.id,
+ name=network.name)\
+ .AndReturn(network)
+ api.quantum.network_get(IsA(http.HttpRequest), network.id)\
+ .AndReturn(network)
+ self.mox.ReplayAll()
+
+ formData = {'network_id': network.id,
+ 'name': network.name,
+ 'tenant_id': network.tenant_id}
+ url = reverse('horizon:project:networks:update', args=[network.id])
+ res = self.client.post(url, formData)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('network_modify',
+ 'network_get',)})
+ def test_network_update_post_exception(self):
+ network = self.networks.first()
+ api.quantum.network_modify(IsA(http.HttpRequest), network.id,
+ name=network.name)\
+ .AndRaise(self.exceptions.quantum)
+ api.quantum.network_get(IsA(http.HttpRequest), network.id)\
+ .AndReturn(network)
+ self.mox.ReplayAll()
+
+ form_data = {'network_id': network.id,
+ 'name': network.name,
+ 'tenant_id': network.tenant_id}
+ url = reverse('horizon:project:networks:update', args=[network.id])
+ res = self.client.post(url, form_data)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('network_list',
+ 'subnet_list',
+ 'network_delete')})
+ def test_delete_network_no_subnet(self):
+ network = self.networks.first()
+ api.quantum.network_list(IsA(http.HttpRequest),
+ tenant_id=network.tenant_id,
+ shared=False)\
+ .AndReturn([network])
+ api.quantum.network_list(IsA(http.HttpRequest),
+ shared=True)\
+ .AndReturn([])
+ api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network.id)\
+ .AndReturn([])
+ api.quantum.network_delete(IsA(http.HttpRequest), network.id)
+
+ self.mox.ReplayAll()
+
+ form_data = {'action': 'networks__delete__%s' % network.id}
+ res = self.client.post(INDEX_URL, form_data)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('network_list',
+ 'subnet_list',
+ 'network_delete',
+ 'subnet_delete')})
+ def test_delete_network_with_subnet(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ api.quantum.network_list(IsA(http.HttpRequest),
+ tenant_id=network.tenant_id,
+ shared=False)\
+ .AndReturn([network])
+ api.quantum.network_list(IsA(http.HttpRequest), shared=True)\
+ .AndReturn([])
+ api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network.id)\
+ .AndReturn([subnet])
+ api.quantum.subnet_delete(IsA(http.HttpRequest), subnet.id)
+ api.quantum.network_delete(IsA(http.HttpRequest), network.id)
+
+ self.mox.ReplayAll()
+
+ form_data = {'action': 'networks__delete__%s' % network.id}
+ res = self.client.post(INDEX_URL, form_data)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('network_list',
+ 'subnet_list',
+ 'network_delete',
+ 'subnet_delete')})
+ def test_delete_network_exception(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ api.quantum.network_list(IsA(http.HttpRequest),
+ tenant_id=network.tenant_id,
+ shared=False)\
+ .AndReturn([network])
+ api.quantum.network_list(IsA(http.HttpRequest),
+ shared=True)\
+ .AndReturn([])
+ api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network.id)\
+ .AndReturn([subnet])
+ api.quantum.subnet_delete(IsA(http.HttpRequest), subnet.id)
+ api.quantum.network_delete(IsA(http.HttpRequest), network.id)\
+ .AndRaise(self.exceptions.quantum)
+
+ self.mox.ReplayAll()
+
+ form_data = {'action': 'networks__delete__%s' % network.id}
+ res = self.client.post(INDEX_URL, form_data)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('subnet_get',)})
+ def test_subnet_detail(self):
+ subnet = self.subnets.first()
+ api.quantum.subnet_get(IsA(http.HttpRequest), subnet.id)\
+ .AndReturn(self.subnets.first())
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:networks:subnets:detail',
+ args=[subnet.id])
+ res = self.client.get(url)
+
+ self.assertTemplateUsed(res, 'project/networks/subnets/detail.html')
+ self.assertEqual(res.context['subnet'].id, subnet.id)
+
+ @test.create_stubs({api.quantum: ('subnet_get',)})
+ def test_subnet_detail_exception(self):
+ subnet = self.subnets.first()
+ api.quantum.subnet_get(IsA(http.HttpRequest), subnet.id)\
+ .AndRaise(self.exceptions.quantum)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:networks:subnets:detail',
+ args=[subnet.id])
+ res = self.client.get(url)
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('network_get',)})
+ def test_subnet_create_get(self):
+ network = self.networks.first()
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:networks:addsubnet',
+ args=[network.id])
+ res = self.client.get(url)
+
+ self.assertTemplateUsed(res, 'project/networks/subnets/create.html')
+
+ @test.create_stubs({api.quantum: ('network_get',
+ 'subnet_create',)})
+ def test_subnet_create_post(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ api.quantum.subnet_create(IsA(http.HttpRequest),
+ network_id=network.id,
+ network_name=network.name,
+ name=subnet.name,
+ cidr=subnet.cidr,
+ ip_version=subnet.ip_version,
+ gateway_ip=subnet.gateway_ip)\
+ .AndReturn(subnet)
+ self.mox.ReplayAll()
+
+ form_data = {'network_id': subnet.network_id,
+ 'network_name': network.name,
+ 'name': subnet.name,
+ 'cidr': subnet.cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': subnet.gateway_ip}
+ url = reverse('horizon:project:networks:addsubnet',
+ args=[subnet.network_id])
+ res = self.client.post(url, form_data)
+
+ self.assertNoFormErrors(res)
+ redir_url = reverse('horizon:project:networks:detail',
+ args=[subnet.network_id])
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('network_get',
+ 'subnet_create',)})
+ def test_subnet_create_post_network_exception(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndRaise(self.exceptions.quantum)
+ self.mox.ReplayAll()
+
+ form_data = {'network_id': subnet.network_id,
+ 'network_name': network.name,
+ 'name': subnet.name,
+ 'cidr': subnet.cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': subnet.gateway_ip}
+ url = reverse('horizon:project:networks:addsubnet',
+ args=[subnet.network_id])
+ res = self.client.post(url, form_data)
+
+ self.assertNoFormErrors(res)
+ self.assertRedirectsNoFollow(res, INDEX_URL)
+
+ @test.create_stubs({api.quantum: ('network_get',
+ 'subnet_create',)})
+ def test_subnet_create_post_subnet_exception(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ api.quantum.subnet_create(IsA(http.HttpRequest),
+ network_id=network.id,
+ network_name=network.name,
+ name=subnet.name,
+ cidr=subnet.cidr,
+ ip_version=subnet.ip_version,
+ gateway_ip=subnet.gateway_ip)\
+ .AndRaise(self.exceptions.quantum)
+ self.mox.ReplayAll()
+
+ form_data = {'network_id': subnet.network_id,
+ 'network_name': network.name,
+ 'name': subnet.name,
+ 'cidr': subnet.cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': subnet.gateway_ip}
+ url = reverse('horizon:project:networks:addsubnet',
+ args=[subnet.network_id])
+ res = self.client.post(url, form_data)
+
+ redir_url = reverse('horizon:project:networks:detail',
+ args=[subnet.network_id])
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('network_get',)})
+ def test_subnet_create_post_cidr_inconsistent(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ self.mox.ReplayAll()
+
+ # dummy IPv6 address
+ cidr = '2001:0DB8:0:CD30:123:4567:89AB:CDEF/60'
+ form_data = {'network_id': subnet.network_id,
+ 'network_name': network.name,
+ 'name': subnet.name,
+ 'cidr': cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': subnet.gateway_ip}
+ url = reverse('horizon:project:networks:addsubnet',
+ args=[subnet.network_id])
+ res = self.client.post(url, form_data)
+
+ expected_msg = 'Network Address and IP version are inconsistent.'
+ self.assertContains(res, expected_msg)
+
+ @test.create_stubs({api.quantum: ('network_get',)})
+ def test_subnet_create_post_gw_inconsistent(self):
+ network = self.networks.first()
+ subnet = self.subnets.first()
+ api.quantum.network_get(IsA(http.HttpRequest),
+ network.id)\
+ .AndReturn(self.networks.first())
+ self.mox.ReplayAll()
+
+ # dummy IPv6 address
+ gateway_ip = '2001:0DB8:0:CD30:123:4567:89AB:CDEF'
+ form_data = {'network_id': subnet.network_id,
+ 'network_name': network.name,
+ 'name': subnet.name,
+ 'cidr': subnet.cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': gateway_ip}
+ url = reverse('horizon:project:networks:addsubnet',
+ args=[subnet.network_id])
+ res = self.client.post(url, form_data)
+
+ self.assertContains(res, 'Gateway IP and IP version are inconsistent.')
+
+ @test.create_stubs({api.quantum: ('subnet_modify',
+ 'subnet_get',)})
+ def test_subnet_update_post(self):
+ subnet = self.subnets.first()
+ api.quantum.subnet_get(IsA(http.HttpRequest), subnet.id)\
+ .AndReturn(subnet)
+ api.quantum.subnet_modify(IsA(http.HttpRequest), subnet.id,
+ name=subnet.name,
+ gateway_ip=subnet.gateway_ip)\
+ .AndReturn(subnet)
+ self.mox.ReplayAll()
+
+ formData = {'network_id': subnet.network_id,
+ 'subnet_id': subnet.id,
+ 'name': subnet.name,
+ 'cidr': subnet.cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': subnet.gateway_ip}
+ url = reverse('horizon:project:networks:editsubnet',
+ args=[subnet.network_id, subnet.id])
+ res = self.client.post(url, formData)
+
+ redir_url = reverse('horizon:project:networks:detail',
+ args=[subnet.network_id])
+ self.assertRedirectsNoFollow(res, redir_url)
+
+ @test.create_stubs({api.quantum: ('subnet_modify',
+ 'subnet_get',)})
+ def test_subnet_update_post_gw_inconsistent(self):
+ subnet = self.subnets.first()
+ api.quantum.subnet_get(IsA(http.HttpRequest), subnet.id)\
+ .AndReturn(subnet)
+ self.mox.ReplayAll()
+
+ # dummy IPv6 address
+ gateway_ip = '2001:0DB8:0:CD30:123:4567:89AB:CDEF'
+ formData = {'network_id': subnet.network_id,
+ 'subnet_id': subnet.id,
+ 'name': subnet.name,
+ 'cidr': subnet.cidr,
+ 'ip_version': subnet.ip_version,
+ 'gateway_ip': gateway_ip}
+ url = reverse('horizon:project:networks:editsubnet',
+ args=[subnet.network_id, subnet.id])
+ res = self.client.post(url, formData)
+
+ self.assertContains(res, 'Gateway IP and IP version are inconsistent.')
+
+ @test.create_stubs({api.quantum: ('subnet_delete',
+ 'subnet_list',
+ 'network_get',
+ 'port_list',)})
+ def test_subnet_delete(self):
+ subnet = self.subnets.first()
+ network_id = subnet.network_id
+ api.quantum.subnet_delete(IsA(http.HttpRequest), subnet.id)
+ api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.subnets.first()])
+ api.quantum.network_get(IsA(http.HttpRequest), network_id)\
+ .AndReturn(self.networks.first())
+ api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.ports.first()])
+ # Called from SubnetTable
+ api.quantum.network_get(IsA(http.HttpRequest), network_id)\
+ .AndReturn(self.networks.first())
+ self.mox.ReplayAll()
+
+ formData = {'action': 'subnets__delete__%s' % subnet.id}
+ url = reverse('horizon:project:networks:detail',
+ args=[network_id])
+ res = self.client.post(url, formData)
+
+ self.assertRedirectsNoFollow(res, url)
+
+ @test.create_stubs({api.quantum: ('subnet_delete',
+ 'subnet_list',
+ 'network_get',
+ 'port_list',)})
+ def test_subnet_delete_excceeption(self):
+ subnet = self.subnets.first()
+ network_id = subnet.network_id
+ api.quantum.subnet_delete(IsA(http.HttpRequest), subnet.id)\
+ .AndRaise(self.exceptions.quantum)
+ api.quantum.subnet_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.subnets.first()])
+ api.quantum.network_get(IsA(http.HttpRequest), network_id)\
+ .AndReturn(self.networks.first())
+ api.quantum.port_list(IsA(http.HttpRequest), network_id=network_id)\
+ .AndReturn([self.ports.first()])
+ # Called from SubnetTable
+ api.quantum.network_get(IsA(http.HttpRequest), network_id)\
+ .AndReturn(self.networks.first())
+ self.mox.ReplayAll()
+
+ formData = {'action': 'subnets__delete__%s' % subnet.id}
+ url = reverse('horizon:project:networks:detail',
+ args=[network_id])
+ res = self.client.post(url, formData)
+
+ self.assertRedirectsNoFollow(res, url)
+
+ @test.create_stubs({api.quantum: ('port_get',)})
+ def test_port_detail(self):
+ port = self.ports.first()
+ api.quantum.port_get(IsA(http.HttpRequest), port.id)\
+ .AndReturn(self.ports.first())
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:project:networks:ports:detail',
+ args=[port.id]))
+
+ self.assertTemplateUsed(res, 'project/networks/ports/detail.html')
+ self.assertEqual(res.context['port'].id, port.id)
+
+ @test.create_stubs({api.quantum: ('port_get',)})
+ def test_port_detail_exception(self):
+ port = self.ports.first()
+ api.quantum.port_get(IsA(http.HttpRequest), port.id)\
+ .AndRaise(self.exceptions.quantum)
+
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:project:networks:ports:detail',
+ args=[port.id]))
+
+ self.assertRedirectsNoFollow(res, INDEX_URL)
diff --git a/openstack_dashboard/dashboards/project/networks/urls.py b/openstack_dashboard/dashboards/project/networks/urls.py
new file mode 100644
index 000000000..ee856cb37
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/urls.py
@@ -0,0 +1,39 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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.defaults import patterns, url, include
+
+from .views import IndexView, CreateView, DetailView, UpdateView
+from .subnets.views import CreateView as AddSubnetView
+from .subnets.views import UpdateView as EditSubnetView
+from .subnets import urls as subnet_urls
+from .ports import urls as port_urls
+
+
+NETWORKS = r'^(?P<network_id>[^/]+)/%s$'
+
+
+urlpatterns = patterns('',
+ url(r'^$', IndexView.as_view(), name='index'),
+ url(r'^create$', CreateView.as_view(), name='create'),
+ url(NETWORKS % 'detail', DetailView.as_view(), name='detail'),
+ url(NETWORKS % 'update', UpdateView.as_view(), name='update'),
+ url(NETWORKS % 'subnets/create', AddSubnetView.as_view(),
+ name='addsubnet'),
+ url(r'^(?P<network_id>[^/]+)/subnets/(?P<subnet_id>[^/]+)/update$',
+ EditSubnetView.as_view(), name='editsubnet'),
+ url(r'^subnets/', include(subnet_urls, namespace='subnets')),
+ url(r'^ports/', include(port_urls, namespace='ports')))
diff --git a/openstack_dashboard/dashboards/project/networks/views.py b/openstack_dashboard/dashboards/project/networks/views.py
new file mode 100644
index 000000000..dbc5d18fa
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/views.py
@@ -0,0 +1,143 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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.
+
+"""
+Views for managing Quantum Networks.
+"""
+import logging
+
+from django.core.urlresolvers import reverse_lazy
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import tables
+from horizon import workflows
+
+from openstack_dashboard import api
+from .tables import NetworksTable
+from .subnets.tables import SubnetsTable
+from .ports.tables import PortsTable
+from .forms import UpdateNetwork
+from .workflows import CreateNetwork
+
+
+LOG = logging.getLogger(__name__)
+
+
+class IndexView(tables.DataTableView):
+ table_class = NetworksTable
+ template_name = 'project/networks/index.html'
+
+ def get_data(self):
+ try:
+ tenant_id = self.request.user.tenant_id
+ networks = api.quantum.network_list_for_tenant(self.request,
+ tenant_id)
+ except:
+ networks = []
+ msg = _('Network list can not be retrieved.')
+ exceptions.handle(self.request, msg)
+ for n in networks:
+ n.set_id_as_name_if_empty()
+ return networks
+
+
+class CreateView(workflows.WorkflowView):
+ workflow_class = CreateNetwork
+ template_name = 'project/networks/create.html'
+
+ def get_initial(self):
+ pass
+
+
+class UpdateView(forms.ModalFormView):
+ form_class = UpdateNetwork
+ template_name = 'project/networks/update.html'
+ context_object_name = 'network'
+ success_url = reverse_lazy("horizon:project:networks:index")
+
+ def get_context_data(self, **kwargs):
+ context = super(UpdateView, self).get_context_data(**kwargs)
+ context["network_id"] = self.kwargs['network_id']
+ return context
+
+ def _get_object(self, *args, **kwargs):
+ if not hasattr(self, "_object"):
+ network_id = self.kwargs['network_id']
+ try:
+ self._object = api.quantum.network_get(self.request,
+ network_id)
+ except:
+ redirect = self.success_url
+ msg = _('Unable to retrieve network details.')
+ exceptions.handle(self.request, msg, redirect=redirect)
+ return self._object
+
+ def get_initial(self):
+ network = self._get_object()
+ return {'network_id': network['id'],
+ 'tenant_id': network['tenant_id'],
+ 'name': network['name']}
+
+
+class DetailView(tables.MultiTableView):
+ table_classes = (SubnetsTable, PortsTable)
+ template_name = 'project/networks/detail.html'
+ failure_url = reverse_lazy('horizon:project:networks:index')
+
+ def get_subnets_data(self):
+ try:
+ network = self._get_data()
+ subnets = api.quantum.subnet_list(self.request,
+ network_id=network.id)
+ except:
+ subnets = []
+ msg = _('Subnet list can not be retrieved.')
+ exceptions.handle(self.request, msg)
+ for s in subnets:
+ s.set_id_as_name_if_empty()
+ return subnets
+
+ def get_ports_data(self):
+ try:
+ network_id = self.kwargs['network_id']
+ ports = api.quantum.port_list(self.request, network_id=network_id)
+ except:
+ ports = []
+ msg = _('Port list can not be retrieved.')
+ exceptions.handle(self.request, msg)
+ for p in ports:
+ p.set_id_as_name_if_empty()
+ return ports
+
+ def _get_data(self):
+ if not hasattr(self, "_network"):
+ try:
+ network_id = self.kwargs['network_id']
+ network = api.quantum.network_get(self.request, network_id)
+ network.set_id_as_name_if_empty(length=0)
+ except:
+ msg = _('Unable to retrieve details for network "%s".') \
+ % (network_id)
+ exceptions.handle(self.request, msg, redirect=self.failure_url)
+ self._network = network
+ return self._network
+
+ def get_context_data(self, **kwargs):
+ context = super(DetailView, self).get_context_data(**kwargs)
+ context["network"] = self._get_data()
+ return context
diff --git a/openstack_dashboard/dashboards/project/networks/workflows.py b/openstack_dashboard/dashboards/project/networks/workflows.py
new file mode 100644
index 000000000..54d4a9bf9
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/networks/workflows.py
@@ -0,0 +1,162 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 logging
+import netaddr
+
+from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext as _
+
+from horizon import exceptions
+from horizon import forms
+from horizon import workflows
+from horizon.utils import fields
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateNetworkInfoAction(workflows.Action):
+ net_name = forms.CharField(max_length=255,
+ label=_("Network Name (optional)"),
+ required=False)
+
+ class Meta:
+ name = ("Network")
+ help_text = _("From here you can create a new network.\n"
+ "In addition a subnet associated with the network "
+ "can be created in the next panel.")
+
+
+class CreateNetworkInfo(workflows.Step):
+ action_class = CreateNetworkInfoAction
+ contributes = ("net_name",)
+
+
+class CreateSubnetInfoAction(workflows.Action):
+ with_subnet = forms.BooleanField(label=_("Create Subnet"),
+ initial=True, required=False)
+ subnet_name = forms.CharField(max_length=255,
+ label=_("Subnet Name (optional)"),
+ required=False)
+ cidr = fields.IPField(label=_("Network Address"),
+ required=False,
+ initial="",
+ help_text=_("Network address in CIDR format "
+ "(e.g. 192.168.0.0/24)"),
+ version=fields.IPv4 | fields.IPv6,
+ mask=True)
+ ip_version = forms.ChoiceField(choices=[(4, 'IPv4'), (6, 'IPv6')],
+ label=_("IP Version"))
+ gateway_ip = fields.IPField(label=_("Gateway IP (optional)"),
+ required=False,
+ initial="",
+ help_text=_("IP address of Gateway "
+ "(e.g. 192.168.0.1)"),
+ version=fields.IPv4 | fields.IPv6,
+ mask=False)
+
+ class Meta:
+ name = ("Subnet")
+ help_text = _('You can create a subnet associated with the new '
+ 'network, in which case "Network Address" must be '
+ 'specified. If you wish to create a network WITHOUT a '
+ 'subnet, uncheck the "Create Subnet" checkbox.')
+
+ def clean(self):
+ cleaned_data = super(CreateSubnetInfoAction, self).clean()
+ with_subnet = cleaned_data.get('with_subnet')
+ cidr = cleaned_data.get('cidr')
+ ip_version = int(cleaned_data.get('ip_version'))
+ gateway_ip = cleaned_data.get('gateway_ip')
+ if with_subnet and not cidr:
+ msg = _('Specify "Network Address" or '
+ 'clear "Create Subnet" checkbox.')
+ raise forms.ValidationError(msg)
+ if cidr:
+ if netaddr.IPNetwork(cidr).version is not ip_version:
+ msg = _('Network Address and IP version are inconsistent.')
+ raise forms.ValidationError(msg)
+ if gateway_ip:
+ if netaddr.IPAddress(gateway_ip).version is not ip_version:
+ msg = _('Gateway IP and IP version are inconsistent.')
+ raise forms.ValidationError(msg)
+ return cleaned_data
+
+
+class CreateSubnetInfo(workflows.Step):
+ action_class = CreateSubnetInfoAction
+ contributes = ("with_subnet", "subnet_name", "cidr",
+ "ip_version", "gateway_ip")
+
+
+class CreateNetwork(workflows.Workflow):
+ slug = "create_network"
+ name = _("Create Network")
+ finalize_button_name = _("Create")
+ success_message = _('Created network "%s".')
+ failure_message = _('Unable to create network "%s".')
+ success_url = "horizon:project:networks:index"
+ default_steps = (CreateNetworkInfo,
+ CreateSubnetInfo)
+
+ def format_status_message(self, message):
+ name = self.context.get('net_name') or self.context.get('net_id', '')
+ return message % name
+
+ def handle(self, request, data):
+ # create the network
+ try:
+ network = api.quantum.network_create(request,
+ name=data['net_name'])
+ network.set_id_as_name_if_empty()
+ self.context['net_id'] = network.id
+ msg = _('Network "%s" was successfully created.') % network.name
+ LOG.debug(msg)
+ except:
+ msg = _('Failed to create network "%s".') % data['net_name']
+ LOG.info(msg)
+ redirect = reverse('horizon:project:networks:index')
+ exceptions.handle(request, msg, redirect=redirect)
+ return False
+
+ # If we do not need to create a subnet, return here.
+ if not data['with_subnet']:
+ return True
+
+ # Create the subnet.
+ try:
+ params = {'network_id': network.id,
+ 'name': data['subnet_name'],
+ 'cidr': data['cidr'],
+ 'ip_version': int(data['ip_version'])}
+ if data['gateway_ip']:
+ params['gateway_ip'] = data['gateway_ip']
+ api.quantum.subnet_create(request, **params)
+ msg = _('Subnet "%s" was successfully created.') % data['cidr']
+ LOG.debug(msg)
+ except Exception:
+ msg = _('Failed to create subnet "%(sub)s" for network "%(net)s".')
+ redirect = reverse('horizon:project:networks:index')
+ exceptions.handle(request,
+ msg % {"sub": data['cidr'], "net": network.id},
+ redirect=redirect)
+ return False
+
+ return True
diff --git a/openstack_dashboard/dashboards/project/overview/__init__.py b/openstack_dashboard/dashboards/project/overview/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/overview/__init__.py
diff --git a/openstack_dashboard/dashboards/project/overview/panel.py b/openstack_dashboard/dashboards/project/overview/panel.py
new file mode 100644
index 000000000..7ec447b4f
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/overview/panel.py
@@ -0,0 +1,33 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 Overview(horizon.Panel):
+ name = _("Overview")
+ slug = 'overview'
+
+
+dashboard.Project.register(Overview)
diff --git a/openstack_dashboard/dashboards/project/overview/templates/overview/usage.csv b/openstack_dashboard/dashboards/project/overview/templates/overview/usage.csv
new file mode 100644
index 000000000..a3f52bb35
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/overview/templates/overview/usage.csv
@@ -0,0 +1,11 @@
+Usage Report For Period:,{{ usage.start|date:"b. d Y" }},{{ usage.end|date:"b. d Y" }}
+Tenant ID:,{{ usage.tenant_id }}
+Total Active VCPUs:,{{ usage.summary.instances }}
+CPU-HRs Used:,{{ usage.summary.vcpu_hours }}
+Total Active Ram (MB):,{{ usage.summary.memory_mb }}
+Total Disk Size:,{{ usage.summary.local_gb }}
+Total Disk Usage:,{{ usage.summary.disk_gb_hours }}
+
+Name,VCPUs,RamMB,DiskGB,Usage(Hours),Uptime(Seconds),State
+{% for s in usage.get_instances %}{{ s.name|addslashes }},{{ s.vcpus|addslashes }},{{ s.memory_mb|addslashes }},{{ s.local_gb|addslashes }},{{ s.hours }},{{ s.uptime }},{{ s.state|capfirst|addslashes }}
+{% endfor %}
diff --git a/openstack_dashboard/dashboards/project/overview/templates/overview/usage.html b/openstack_dashboard/dashboards/project/overview/templates/overview/usage.html
new file mode 100644
index 000000000..ecc7d6844
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/overview/templates/overview/usage.html
@@ -0,0 +1,13 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Instance Overview{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Overview") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include "horizon/common/_quota_summary.html" %}
+ {% include "horizon/common/_usage_summary.html" %}
+ {{ table.render }}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/overview/tests.py b/openstack_dashboard/dashboards/project/overview/tests.py
new file mode 100644
index 000000000..dac718ff5
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/overview/tests.py
@@ -0,0 +1,144 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 datetime
+
+from django import http
+from django.core.urlresolvers import reverse
+from django.utils import timezone
+
+from mox import IsA, Func
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+from openstack_dashboard import usage
+
+
+INDEX_URL = reverse('horizon:project:overview:index')
+
+
+class UsageViewTests(test.TestCase):
+ def test_usage(self):
+ now = timezone.now()
+ usage_obj = api.nova.Usage(self.usages.first())
+ quotas = self.quota_usages.first()
+ self.mox.StubOutWithMock(api, 'usage_get')
+ self.mox.StubOutWithMock(api.nova, 'tenant_quota_usages')
+ api.usage_get(IsA(http.HttpRequest), self.tenant.id,
+ datetime.datetime(now.year, now.month, 1, 0, 0, 0),
+ Func(usage.almost_now)) \
+ .AndReturn(usage_obj)
+ api.nova.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(quotas)
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:project:overview:index'))
+ self.assertTemplateUsed(res, 'project/overview/usage.html')
+ self.assertTrue(isinstance(res.context['usage'], usage.TenantUsage))
+ self.assertContains(res, 'form-horizontal')
+
+ def test_unauthorized(self):
+ exc = self.exceptions.keystone_unauthorized
+ now = timezone.now()
+ self.mox.StubOutWithMock(api, 'usage_get')
+ api.usage_get(IsA(http.HttpRequest), self.tenant.id,
+ datetime.datetime(now.year, now.month, 1, 0, 0, 0),
+ Func(usage.almost_now)) \
+ .AndRaise(exc)
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:overview:index')
+ res = self.client.get(url)
+ self.assertRedirects(res, reverse("login") + "?next=" + url)
+
+ def test_usage_csv(self):
+ now = timezone.now()
+ usage_obj = api.nova.Usage(self.usages.first())
+ quotas = self.quota_usages.first()
+ self.mox.StubOutWithMock(api, 'usage_get')
+ self.mox.StubOutWithMock(api.nova, 'tenant_quota_usages')
+ timestamp = datetime.datetime(now.year, now.month, 1, 0, 0, 0)
+ api.usage_get(IsA(http.HttpRequest),
+ self.tenant.id,
+ timestamp,
+ Func(usage.almost_now)) \
+ .AndReturn(usage_obj)
+ api.nova.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(quotas)
+
+ self.mox.ReplayAll()
+ res = self.client.get(reverse('horizon:project:overview:index') +
+ "?format=csv")
+ self.assertTemplateUsed(res, 'project/overview/usage.csv')
+ self.assertTrue(isinstance(res.context['usage'], usage.TenantUsage))
+
+ def test_usage_exception_usage(self):
+ now = timezone.now()
+ quotas = self.quota_usages.first()
+ self.mox.StubOutWithMock(api, 'usage_get')
+ self.mox.StubOutWithMock(api.nova, 'tenant_quota_usages')
+ timestamp = datetime.datetime(now.year, now.month, 1, 0, 0, 0)
+ api.usage_get(IsA(http.HttpRequest),
+ self.tenant.id,
+ timestamp,
+ Func(usage.almost_now)) \
+ .AndRaise(self.exceptions.nova)
+ api.nova.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(quotas)
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:project:overview:index'))
+ self.assertTemplateUsed(res, 'project/overview/usage.html')
+ self.assertEqual(res.context['usage'].usage_list, [])
+
+ def test_usage_exception_quota(self):
+ now = timezone.now()
+ usage_obj = api.nova.Usage(self.usages.first())
+ self.mox.StubOutWithMock(api, 'usage_get')
+ self.mox.StubOutWithMock(api.nova, 'tenant_quota_usages')
+ timestamp = datetime.datetime(now.year, now.month, 1, 0, 0, 0)
+ api.usage_get(IsA(http.HttpRequest),
+ self.tenant.id,
+ timestamp,
+ Func(usage.almost_now)) \
+ .AndReturn(usage_obj)
+ api.nova.tenant_quota_usages(IsA(http.HttpRequest))\
+ .AndRaise(self.exceptions.nova)
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:project:overview:index'))
+ self.assertTemplateUsed(res, 'project/overview/usage.html')
+ self.assertEqual(res.context['usage'].quotas, {})
+
+ def test_usage_default_tenant(self):
+ now = timezone.now()
+ usage_obj = api.nova.Usage(self.usages.first())
+ quotas = self.quota_usages.first()
+ self.mox.StubOutWithMock(api, 'usage_get')
+ self.mox.StubOutWithMock(api.nova, 'tenant_quota_usages')
+ timestamp = datetime.datetime(now.year, now.month, 1, 0, 0, 0)
+ api.usage_get(IsA(http.HttpRequest),
+ self.tenant.id,
+ timestamp,
+ Func(usage.almost_now)) \
+ .AndReturn(usage_obj)
+ api.nova.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(quotas)
+ self.mox.ReplayAll()
+
+ res = self.client.get(reverse('horizon:project:overview:index'))
+ self.assertTemplateUsed(res, 'project/overview/usage.html')
+ self.assertTrue(isinstance(res.context['usage'], usage.TenantUsage))
diff --git a/openstack_dashboard/dashboards/project/overview/urls.py b/openstack_dashboard/dashboards/project/overview/urls.py
new file mode 100644
index 000000000..2a27d3df4
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/overview/urls.py
@@ -0,0 +1,30 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import url, patterns
+
+from .views import ProjectOverview, WarningView
+
+
+urlpatterns = patterns('openstack_dashboard.dashboards.project.overview.views',
+ url(r'^$', ProjectOverview.as_view(), name='index'),
+ url(r'^warning$', WarningView.as_view(), name='warning'),
+)
diff --git a/openstack_dashboard/dashboards/project/overview/views.py b/openstack_dashboard/dashboards/project/overview/views.py
new file mode 100644
index 000000000..32fc3162f
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/overview/views.py
@@ -0,0 +1,37 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.generic import TemplateView
+
+from openstack_dashboard import usage
+
+
+class ProjectOverview(usage.UsageView):
+ table_class = usage.TenantUsageTable
+ usage_class = usage.TenantUsage
+ template_name = 'project/overview/usage.html'
+
+ def get_data(self):
+ super(ProjectOverview, self).get_data()
+ return self.usage.get_instances()
+
+
+class WarningView(TemplateView):
+ template_name = "project/_warning.html"
diff --git a/openstack_dashboard/dashboards/project/volumes/__init__.py b/openstack_dashboard/dashboards/project/volumes/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/__init__.py
diff --git a/openstack_dashboard/dashboards/project/volumes/forms.py b/openstack_dashboard/dashboards/project/volumes/forms.py
new file mode 100644
index 000000000..793f50311
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/forms.py
@@ -0,0 +1,219 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+# All rights reserved.
+
+"""
+Views for managing volumes.
+"""
+
+from django.conf import settings
+from django.core.urlresolvers import reverse
+from django.forms import ValidationError
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import forms
+from horizon import exceptions
+from horizon import messages
+from horizon.utils.fields import SelectWidget
+from horizon.utils.memoized import memoized
+
+from openstack_dashboard import api
+from ..instances.tables import ACTIVE_STATES
+
+
+class CreateForm(forms.SelfHandlingForm):
+ name = forms.CharField(max_length="255", label=_("Volume Name"))
+ description = forms.CharField(widget=forms.Textarea,
+ label=_("Description"), required=False)
+ size = forms.IntegerField(min_value=1, label=_("Size (GB)"))
+ snapshot_source = forms.ChoiceField(label=_("Use snapshot as a source"),
+ widget=SelectWidget(
+ attrs={'class': 'snapshot-selector'},
+ data_attrs=('size', 'display_name'),
+ transform=lambda x:
+ ("%s (%sGB)" % (x.display_name,
+ x.size))),
+ required=False)
+
+ def __init__(self, request, *args, **kwargs):
+ super(CreateForm, self).__init__(request, *args, **kwargs)
+ if ("snapshot_id" in request.GET):
+ try:
+ snapshot = self.get_snapshot(request,
+ request.GET["snapshot_id"])
+ self.fields['name'].initial = snapshot.display_name
+ self.fields['size'].initial = snapshot.size
+ self.fields['snapshot_source'].choices = ((snapshot.id,
+ snapshot),)
+ self.fields['size'].help_text = _('Volume size must be equal '
+ 'to or greater than the snapshot size (%sGB)'
+ % snapshot.size)
+ except:
+ exceptions.handle(request,
+ _('Unable to load the specified snapshot.'))
+ else:
+ try:
+ snapshots = api.volume_snapshot_list(request)
+ if snapshots:
+ choices = [('', _("Choose a snapshot"))] + \
+ [(s.id, s) for s in snapshots]
+ self.fields['snapshot_source'].choices = choices
+ else:
+ del self.fields['snapshot_source']
+ except:
+ exceptions.handle(request, _("Unable to retrieve "
+ "volume snapshots."))
+
+ def handle(self, request, data):
+ try:
+ # FIXME(johnp): cinderclient currently returns a useless
+ # error message when the quota is exceeded when trying to create
+ # a volume, so we need to check for that scenario here before we
+ # send it off to try and create.
+ usages = api.tenant_quota_usages(request)
+
+ snapshot_id = None
+ if (data.get("snapshot_source", None)):
+ # Create from Snapshot
+ snapshot = self.get_snapshot(request,
+ data["snapshot_source"])
+ snapshot_id = snapshot.id
+ if (data['size'] < snapshot.size):
+ error_message = _('The volume size cannot be less than '
+ 'the snapshot size (%sGB)' %
+ snapshot.size)
+ raise ValidationError(error_message)
+ else:
+ if type(data['size']) is str:
+ data['size'] = int(data['size'])
+
+ if usages['gigabytes']['available'] < data['size']:
+ error_message = _('A volume of %(req)iGB cannot be created as '
+ 'you only have %(avail)iGB of your quota '
+ 'available.')
+ params = {'req': data['size'],
+ 'avail': usages['gigabytes']['available']}
+ raise ValidationError(error_message % params)
+ elif usages['volumes']['available'] <= 0:
+ error_message = _('You are already using all of your available'
+ ' volumes.')
+ raise ValidationError(error_message)
+
+ volume = api.volume_create(request,
+ data['size'],
+ data['name'],
+ data['description'],
+ snapshot_id=snapshot_id)
+ message = 'Creating volume "%s"' % data['name']
+ messages.info(request, message)
+ return volume
+ except ValidationError, e:
+ return self.api_error(e.messages[0])
+ except:
+ exceptions.handle(request, ignore=True)
+ return self.api_error(_("Unable to create volume."))
+
+ @memoized
+ def get_snapshot(self, request, id):
+ return api.nova.volume_snapshot_get(request, id)
+
+
+class AttachForm(forms.SelfHandlingForm):
+ instance = forms.ChoiceField(label=_("Attach to Instance"),
+ help_text=_("Select an instance to "
+ "attach to."))
+ device = forms.CharField(label=_("Device Name"))
+
+ def __init__(self, *args, **kwargs):
+ super(AttachForm, self).__init__(*args, **kwargs)
+
+ # Hide the device field if the hypervisor doesn't support it.
+ hypervisor_features = getattr(settings,
+ "OPENSTACK_HYPERVISOR_FEATURES",
+ {})
+ can_set_mount_point = hypervisor_features.get("can_set_mount_point",
+ True)
+ if not can_set_mount_point:
+ self.fields['device'].widget = forms.widgets.HiddenInput()
+ self.fields['device'].required = False
+
+ # populate volume_id
+ volume = kwargs.get('initial', {}).get("volume", None)
+ if volume:
+ volume_id = volume.id
+ else:
+ volume_id = None
+ self.fields['volume_id'] = forms.CharField(widget=forms.HiddenInput(),
+ initial=volume_id)
+
+ # Populate instance choices
+ instance_list = kwargs.get('initial', {}).get('instances', [])
+ instances = []
+ for instance in instance_list:
+ if instance.status in ACTIVE_STATES and \
+ not any(instance.id == att["server_id"]
+ for att in volume.attachments):
+ instances.append((instance.id, '%s (%s)' % (instance.name,
+ instance.id)))
+ if instances:
+ instances.insert(0, ("", _("Select an instance")))
+ else:
+ instances = (("", _("No instances available")),)
+ self.fields['instance'].choices = instances
+
+ def handle(self, request, data):
+ instance_choices = dict(self.fields['instance'].choices)
+ instance_name = instance_choices.get(data['instance'],
+ _("Unknown instance (None)"))
+ # The name of the instance in the choices list has the ID appended to
+ # it, so let's slice that off...
+ instance_name = instance_name.rsplit(" (")[0]
+ try:
+ vol = api.volume_attach(request,
+ data['volume_id'],
+ data['instance'],
+ data.get('device', ''))
+ vol_name = api.volume_get(request, data['volume_id']).display_name
+
+ message = _('Attaching volume %(vol)s to instance '
+ '%(inst)s on %(dev)s.') % {"vol": vol_name,
+ "inst": instance_name,
+ "dev": vol.device}
+ messages.info(request, message)
+ return True
+ except:
+ redirect = reverse("horizon:project:volumes:index")
+ exceptions.handle(request,
+ _('Unable to attach volume.'),
+ redirect=redirect)
+
+
+class CreateSnapshotForm(forms.SelfHandlingForm):
+ name = forms.CharField(max_length="255", label=_("Snapshot Name"))
+ description = forms.CharField(widget=forms.Textarea,
+ label=_("Description"), required=False)
+
+ def __init__(self, request, *args, **kwargs):
+ super(CreateSnapshotForm, self).__init__(request, *args, **kwargs)
+
+ # populate volume_id
+ volume_id = kwargs.get('initial', {}).get('volume_id', [])
+ self.fields['volume_id'] = forms.CharField(widget=forms.HiddenInput(),
+ initial=volume_id)
+
+ def handle(self, request, data):
+ try:
+ snapshot = api.volume_snapshot_create(request,
+ data['volume_id'],
+ data['name'],
+ data['description'])
+
+ message = _('Creating volume snapshot "%s"') % data['name']
+ messages.info(request, message)
+ return snapshot
+ except:
+ redirect = reverse("horizon:project:images_and_snapshots:index")
+ exceptions.handle(request,
+ _('Unable to create volume snapshot.'),
+ redirect=redirect)
diff --git a/openstack_dashboard/dashboards/project/volumes/panel.py b/openstack_dashboard/dashboards/project/volumes/panel.py
new file mode 100644
index 000000000..351e63cf6
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/panel.py
@@ -0,0 +1,30 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 Volumes(horizon.Panel):
+ name = _("Volumes")
+ slug = 'volumes'
+ permissions = ('openstack.services.volume',)
+
+
+dashboard.Project.register(Volumes)
diff --git a/openstack_dashboard/dashboards/project/volumes/tables.py b/openstack_dashboard/dashboards/project/volumes/tables.py
new file mode 100644
index 000000000..4be2ba88f
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/tables.py
@@ -0,0 +1,227 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django.core.urlresolvers import reverse, NoReverseMatch
+from django.template.defaultfilters import title
+from django.utils import safestring
+from django.utils.html import strip_tags
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tables
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+DELETABLE_STATES = ("available", "error")
+
+
+class DeleteVolume(tables.DeleteAction):
+ data_type_singular = _("Volume")
+ data_type_plural = _("Volumes")
+
+ def delete(self, request, obj_id):
+ obj = self.table.get_object_by_id(obj_id)
+ name = self.table.get_object_display(obj)
+ try:
+ api.volume_delete(request, obj_id)
+ except:
+ msg = _('Unable to delete volume "%s". One or more snapshots '
+ 'depend on it.')
+ exceptions.check_message(["snapshots", "dependent"], msg % name)
+ raise
+
+ def allowed(self, request, volume=None):
+ if volume:
+ return volume.status in DELETABLE_STATES
+ return True
+
+
+class CreateVolume(tables.LinkAction):
+ name = "create"
+ verbose_name = _("Create Volume")
+ url = "horizon:project:volumes:create"
+ classes = ("ajax-modal", "btn-create")
+
+
+class EditAttachments(tables.LinkAction):
+ name = "attachments"
+ verbose_name = _("Edit Attachments")
+ url = "horizon:project:volumes:attach"
+ classes = ("ajax-modal", "btn-edit")
+
+ def allowed(self, request, volume=None):
+ return volume.status in ("available", "in-use")
+
+
+class CreateSnapshot(tables.LinkAction):
+ name = "snapshots"
+ verbose_name = _("Create Snapshot")
+ url = "horizon:project:volumes:create_snapshot"
+ classes = ("ajax-modal", "btn-camera")
+
+ def allowed(self, request, volume=None):
+ return volume.status == "available"
+
+
+class UpdateRow(tables.Row):
+ ajax = True
+
+ def get_data(self, request, volume_id):
+ volume = api.volume_get(request, volume_id)
+ return volume
+
+
+def get_size(volume):
+ return _("%sGB") % volume.size
+
+
+def get_attachment_name(request, attachment):
+ server_id = attachment.get("server_id", None)
+ if "instance" in attachment and attachment['instance']:
+ name = attachment["instance"].name
+ else:
+ try:
+ server = api.nova.server_get(request, server_id)
+ name = server.name
+ except:
+ name = None
+ exceptions.handle(request, _("Unable to retrieve "
+ "attachment information."))
+ try:
+ url = reverse("horizon:project:instances:detail", args=(server_id,))
+ instance = '<a href="%s">%s</a>' % (url, name)
+ except NoReverseMatch:
+ instance = name
+ return instance
+
+
+class AttachmentColumn(tables.Column):
+ """
+ Customized column class that does complex processing on the attachments
+ for a volume instance.
+ """
+ def get_raw_data(self, volume):
+ request = self.table.request
+ link = _('Attached to %(instance)s on %(dev)s')
+ attachments = []
+ # Filter out "empty" attachments which the client returns...
+ for attachment in [att for att in volume.attachments if att]:
+ # When a volume is attached it may return the server_id
+ # without the server name...
+ instance = get_attachment_name(request, attachment)
+ vals = {"instance": instance,
+ "dev": attachment["device"]}
+ attachments.append(link % vals)
+ return safestring.mark_safe(", ".join(attachments))
+
+
+class VolumesTableBase(tables.DataTable):
+ STATUS_CHOICES = (
+ ("in-use", True),
+ ("available", True),
+ ("creating", None),
+ ("error", False),
+ )
+ name = tables.Column("display_name",
+ verbose_name=_("Name"),
+ link="horizon:project:volumes:detail")
+ description = tables.Column("display_description",
+ verbose_name=_("Description"),
+ truncate=40)
+ size = tables.Column(get_size,
+ verbose_name=_("Size"),
+ attrs={'data-type': 'size'})
+ status = tables.Column("status",
+ filters=(title,),
+ verbose_name=_("Status"),
+ status=True,
+ status_choices=STATUS_CHOICES)
+
+ def get_object_display(self, obj):
+ return obj.display_name
+
+
+class VolumesTable(VolumesTableBase):
+ name = tables.Column("display_name",
+ verbose_name=_("Name"),
+ link="horizon:project:volumes:detail")
+ attachments = AttachmentColumn("attachments",
+ verbose_name=_("Attached To"))
+
+ class Meta:
+ name = "volumes"
+ verbose_name = _("Volumes")
+ status_columns = ["status"]
+ row_class = UpdateRow
+ table_actions = (CreateVolume, DeleteVolume,)
+ row_actions = (EditAttachments, CreateSnapshot, DeleteVolume)
+
+
+class DetachVolume(tables.BatchAction):
+ name = "detach"
+ action_present = _("Detach")
+ action_past = _("Detaching") # This action is asynchronous.
+ data_type_singular = _("Volume")
+ data_type_plural = _("Volumes")
+ classes = ('btn-danger', 'btn-detach')
+
+ def action(self, request, obj_id):
+ attachment = self.table.get_object_by_id(obj_id)
+ api.volume_detach(request, attachment.get('server_id', None), obj_id)
+
+ def get_success_url(self, request):
+ return reverse('horizon:project:volumes:index')
+
+
+class AttachedInstanceColumn(tables.Column):
+ """
+ Customized column class that does complex processing on the attachments
+ for a volume instance.
+ """
+ def get_raw_data(self, attachment):
+ request = self.table.request
+ return safestring.mark_safe(get_attachment_name(request, attachment))
+
+
+class AttachmentsTable(tables.DataTable):
+ instance = AttachedInstanceColumn(get_attachment_name,
+ verbose_name=_("Instance"))
+ device = tables.Column("device")
+
+ def get_object_id(self, obj):
+ return obj['id']
+
+ def get_object_display(self, attachment):
+ instance_name = get_attachment_name(self.request, attachment)
+ vals = {"dev": attachment['device'],
+ "instance_name": strip_tags(instance_name)}
+ return _("%(dev)s on instance %(instance_name)s") % vals
+
+ def get_object_by_id(self, obj_id):
+ for obj in self.data:
+ if self.get_object_id(obj) == obj_id:
+ return obj
+ raise ValueError('No match found for the id "%s".' % obj_id)
+
+ class Meta:
+ name = "attachments"
+ table_actions = (DetachVolume,)
+ row_actions = (DetachVolume,)
diff --git a/openstack_dashboard/dashboards/project/volumes/tabs.py b/openstack_dashboard/dashboards/project/volumes/tabs.py
new file mode 100644
index 000000000..0d00ed899
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/tabs.py
@@ -0,0 +1,49 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import tabs
+
+from openstack_dashboard import api
+
+
+class OverviewTab(tabs.Tab):
+ name = _("Overview")
+ slug = "overview"
+ template_name = ("project/volumes/"
+ "_detail_overview.html")
+
+ def get_context_data(self, request):
+ volume_id = self.tab_group.kwargs['volume_id']
+ try:
+ volume = api.nova.volume_get(request, volume_id)
+ for att in volume.attachments:
+ att['instance'] = api.nova.server_get(request,
+ att['server_id'])
+ except:
+ redirect = reverse('horizon:project:volumes:index')
+ exceptions.handle(self.request,
+ _('Unable to retrieve volume details.'),
+ redirect=redirect)
+ return {'volume': volume}
+
+
+class VolumeDetailTabs(tabs.TabGroup):
+ slug = "volume_details"
+ tabs = (OverviewTab,)
diff --git a/openstack_dashboard/dashboards/project/volumes/templates/volumes/_attach.html b/openstack_dashboard/dashboards/project/volumes/templates/volumes/_attach.html
new file mode 100644
index 000000000..7712bb7da
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/templates/volumes/_attach.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}attach_volume_form{% endblock %}
+{% block form_action %}{% url horizon:project:volumes:attach volume.id %}{% endblock %}
+{% block form_class %}{{ block.super }} horizontal {% if show_attach %}split_half{% else %} no_split{% endif %}{% endblock %}
+
+{% block modal_id %}attach_volume_modal{% endblock %}
+{% block modal-header %}{% trans "Manage Volume Attachments" %}{% endblock %}
+
+{% block modal-body %}
+ {% if show_attach %}
+ <h3>{% trans "Attach To Instance" %}</h3>
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+ {% endif %}
+{% endblock %}
+
+{% block modal-footer %}
+ {% if show_attach %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Attach Volume" %}" />
+ {% endif %}
+ <a href="{% url horizon:project:volumes:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/volumes/templates/volumes/_create.html b/openstack_dashboard/dashboards/project/volumes/templates/volumes/_create.html
new file mode 100644
index 000000000..1c5164513
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/templates/volumes/_create.html
@@ -0,0 +1,57 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n horizon humanize %}
+
+{% block form_id %}{% endblock %}
+{% block form_action %}{% url horizon:project:volumes:create %}?{{ request.GET.urlencode }}{% endblock %}
+
+{% block modal_id %}create_volume_modal{% endblock %}
+{% block modal-header %}{% trans "Create Volume" %}{% 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>{% trans "Volumes are block devices that can be attached to instances." %}</p>
+
+ <h3>{% trans "Volume Quotas" %}</h3>
+
+ <div class="quota_title clearfix">
+ <strong>{% trans "Total Gigabytes" %} <span>({{ usages.gigabytes.used|intcomma }} GB)</span></strong>
+ <p>{{ usages.gigabytes.available|quota:"GB"|intcomma }}</p>
+ </div>
+
+ <div id="quota_size" data-progress-indicator-for="id_size" data-quota-limit="{{ usages.gigabytes.quota }}" data-quota-used="{{ usages.gigabytes.used }}" class="quota_bar">
+ {% horizon_progress_bar usages.gigabytes.used usages.gigabytes.quota %}
+ </div>
+
+ <div class="quota_title clearfix">
+ <strong>{% trans "Number of Volumes" %} <span>({{ usages.volumes.used|intcomma }})</span></strong>
+ <p>{{ usages.volumes.available|quota|intcomma }}</p>
+ </div>
+
+ <div id="quota_volumes" data-progress-indicator-step-by="1" data-quota-limit="{{ usages.volumes.quota }}" data-quota-used="{{ usages.volumes.used }}" class="quota_bar">
+ {% horizon_progress_bar usages.volumes.used usages.volumes.quota %}
+ </div>
+ </div>
+
+ <script type="text/javascript" charset="utf-8">
+ if(typeof horizon.Quota !== 'undefined') {
+ horizon.Quota.init();
+ } else {
+ addHorizonLoadEvent(function() {
+ horizon.Quota.init();
+ });
+ }
+ </script>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Volume" %}" />
+ <a href="{% url horizon:project:volumes:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/volumes/templates/volumes/_create_snapshot.html b/openstack_dashboard/dashboards/project/volumes/templates/volumes/_create_snapshot.html
new file mode 100644
index 000000000..ab05b5b31
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/templates/volumes/_create_snapshot.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}{% endblock %}
+{% block form_action %}{% url horizon:project:volumes:create_snapshot volume_id %}{% endblock %}
+
+{% block modal_id %}create_volume_snapshot_modal{% endblock %}
+{% block modal-header %}{% trans "Create Volume Snapshot" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description" %}:</h3>
+ <p>{% trans "Volumes are block devices that can be attached to instances." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right" type="submit" value="{% trans "Create Volume Snapshot" %}" />
+ <a href="{% url horizon:project:volumes:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/volumes/templates/volumes/_detail_overview.html b/openstack_dashboard/dashboards/project/volumes/templates/volumes/_detail_overview.html
new file mode 100644
index 000000000..145c63a9d
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/templates/volumes/_detail_overview.html
@@ -0,0 +1,49 @@
+{% load i18n sizeformat parse_date %}
+
+<h3>{% trans "Volume Overview" %}: {{volume.display_name }}</h3>
+
+<div class="info row-fluid detail">
+ <h4>{% trans "Info" %}</h4>
+ <hr class="header_rule">
+ <dl>
+ <dt>{% trans "Name" %}</dt>
+ <dd>{{ volume.display_name }}</dd>
+ <dt>{% trans "ID" %}</dt>
+ <dd>{{ volume.id }}</dd>
+ {% if volume.display_description %}
+ <dt>{% trans "Description" %}</dt>
+ <dd>{{ volume.display_description }}</dd>
+ {% endif %}
+ <dt>{% trans "Status" %}</dt>
+ <dd>{{ volume.status|capfirst }}</dd>
+ </dl>
+</div>
+
+<div class="specs row-fluid detail">
+ <h4>{% trans "Specs" %}</h4>
+ <hr class="header_rule">
+ <dl>
+ <dt>{% trans "Size" %}</dt>
+ <dd>{{ volume.size }} {% trans "GB" %}</dd>
+ <dt>{% trans "Created" %}</dt>
+ <dd>{{ volume.created_at|parse_date }}</dd>
+ </dl>
+</div>
+
+<div class="status row-fluid detail">
+ <h4>{% trans "Attachments" %}</h4>
+ <hr class="header_rule">
+ <dl>
+ {% for attachment in volume.attachments %}
+ <dt>{% trans "Attached To" %}</dt>
+ <dd>
+ {% url horizon:project:instances:detail attachment.server_id as instance_url%}
+ <a href="{{ instance_url }}">{{ attachment.instance.name }}</a>
+ <span> {% trans "on" %} {{ attachment.device }}</span>
+ </dd>
+ {% empty %}
+ <dt>{% trans "Attached To" %}</dt>
+ <dd><em>{% trans "Not attached" %}</em></dd>
+ {% endfor %}
+ </dl>
+</div>
diff --git a/openstack_dashboard/dashboards/project/volumes/templates/volumes/attach.html b/openstack_dashboard/dashboards/project/volumes/templates/volumes/attach.html
new file mode 100644
index 000000000..23f6e23b9
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/templates/volumes/attach.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Manage Volume Attachments{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Manage Volume Attachments") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'project/volumes/_attach.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/volumes/templates/volumes/create.html b/openstack_dashboard/dashboards/project/volumes/templates/volumes/create.html
new file mode 100644
index 000000000..3f4eadef9
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/templates/volumes/create.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}Create Volume{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Create a Volume") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'project/volumes/_create.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/volumes/templates/volumes/create_snapshot.html b/openstack_dashboard/dashboards/project/volumes/templates/volumes/create_snapshot.html
new file mode 100644
index 000000000..4aa6562eb
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/templates/volumes/create_snapshot.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Create Volume Snapshot" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Create a Volume Snapshot") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include 'project/volumes/_create_snapshot.html' %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/volumes/templates/volumes/detail.html b/openstack_dashboard/dashboards/project/volumes/templates/volumes/detail.html
new file mode 100644
index 000000000..9dbbd4084
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/templates/volumes/detail.html
@@ -0,0 +1,15 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Volume Details" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Volume Detail") %}
+{% endblock page_header %}
+
+{% block main %}
+<div class="row-fluid">
+ <div class="span12">
+ {{ tab_group.render }}
+ </div>
+</div>
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/volumes/templates/volumes/index.html b/openstack_dashboard/dashboards/project/volumes/templates/volumes/index.html
new file mode 100644
index 000000000..201e77426
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/templates/volumes/index.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Volumes" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Volumes") %}
+{% endblock page_header %}
+
+{% block main %}
+ {{ table.render }}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/project/volumes/tests.py b/openstack_dashboard/dashboards/project/volumes/tests.py
new file mode 100644
index 000000000..3c28442fa
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/tests.py
@@ -0,0 +1,329 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 import http
+from django.conf import settings
+from django.core.urlresolvers import reverse
+from django.forms import widgets
+
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+class VolumeViewTests(test.TestCase):
+ @test.create_stubs({api: ('tenant_quota_usages', 'volume_create',
+ 'volume_snapshot_list')})
+ def test_create_volume(self):
+ volume = self.volumes.first()
+ usage = {'gigabytes': {'available': 250}, 'volumes': {'available': 6}}
+ formData = {'name': u'A Volume I Am Making',
+ 'description': u'This is a volume I am making for a test.',
+ 'method': u'CreateForm',
+ 'size': 50, 'snapshot_source': ''}
+
+ api.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(usage)
+ api.volume_snapshot_list(IsA(http.HttpRequest)).\
+ AndReturn(self.volume_snapshots.list())
+ api.volume_create(IsA(http.HttpRequest),
+ formData['size'],
+ formData['name'],
+ formData['description'],
+ snapshot_id=None).AndReturn(volume)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:volumes:create')
+ res = self.client.post(url, formData)
+
+ redirect_url = reverse('horizon:project:volumes:index')
+ self.assertRedirectsNoFollow(res, redirect_url)
+
+ @test.create_stubs({api: ('tenant_quota_usages', 'volume_create',
+ 'volume_snapshot_list'),
+ api.nova: ('volume_snapshot_get',)})
+ def test_create_volume_from_snapshot(self):
+ volume = self.volumes.first()
+ usage = {'gigabytes': {'available': 250}, 'volumes': {'available': 6}}
+ snapshot = self.volume_snapshots.first()
+ formData = {'name': u'A Volume I Am Making',
+ 'description': u'This is a volume I am making for a test.',
+ 'method': u'CreateForm',
+ 'size': 50, 'snapshot_source': snapshot.id}
+
+ # first call- with url param
+ api.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(usage)
+ api.nova.volume_snapshot_get(IsA(http.HttpRequest),
+ str(snapshot.id)).AndReturn(snapshot)
+ api.volume_create(IsA(http.HttpRequest),
+ formData['size'],
+ formData['name'],
+ formData['description'],
+ snapshot_id=snapshot.id).\
+ AndReturn(volume)
+ # second call- with dropdown
+ api.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(usage)
+ api.volume_snapshot_list(IsA(http.HttpRequest)).\
+ AndReturn(self.volume_snapshots.list())
+ api.nova.volume_snapshot_get(IsA(http.HttpRequest),
+ str(snapshot.id)).AndReturn(snapshot)
+ api.volume_create(IsA(http.HttpRequest),
+ formData['size'],
+ formData['name'],
+ formData['description'],
+ snapshot_id=snapshot.id).\
+ AndReturn(volume)
+
+ self.mox.ReplayAll()
+
+ # get snapshot from url
+ url = reverse('horizon:project:volumes:create')
+ res = self.client.post("?".join([url,
+ "snapshot_id=" + str(snapshot.id)]),
+ formData)
+
+ redirect_url = reverse('horizon:project:volumes:index')
+ self.assertRedirectsNoFollow(res, redirect_url)
+
+ # get snapshot from dropdown list
+ url = reverse('horizon:project:volumes:create')
+ res = self.client.post(url, formData)
+
+ redirect_url = reverse('horizon:project:volumes:index')
+ self.assertRedirectsNoFollow(res, redirect_url)
+
+ @test.create_stubs({api: ('tenant_quota_usages',),
+ api.nova: ('volume_snapshot_get',)})
+ def test_create_volume_from_snapshot_invalid_size(self):
+ usage = {'gigabytes': {'available': 250}, 'volumes': {'available': 6}}
+ snapshot = self.volume_snapshots.first()
+ formData = {'name': u'A Volume I Am Making',
+ 'description': u'This is a volume I am making for a test.',
+ 'method': u'CreateForm',
+ 'size': 20, 'snapshot_source': snapshot.id}
+
+ api.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(usage)
+ api.nova.volume_snapshot_get(IsA(http.HttpRequest),
+ str(snapshot.id)).AndReturn(snapshot)
+ api.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(usage)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:volumes:create')
+ res = self.client.post("?".join([url,
+ "snapshot_id=" + str(snapshot.id)]),
+ formData, follow=True)
+ self.assertEqual(res.redirect_chain, [])
+ self.assertFormError(res, 'form', None,
+ "The volume size cannot be less than the "
+ "snapshot size (40GB)")
+
+ @test.create_stubs({api: ('tenant_quota_usages', 'volume_snapshot_list')})
+ def test_create_volume_gb_used_over_alloted_quota(self):
+ usage = {'gigabytes': {'available': 100, 'used': 20}}
+ formData = {'name': u'This Volume Is Huge!',
+ 'description': u'This is a volume that is just too big!',
+ 'method': u'CreateForm',
+ 'size': 5000}
+
+ api.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(usage)
+ api.volume_snapshot_list(IsA(http.HttpRequest)).\
+ AndReturn(self.volume_snapshots.list())
+ api.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(usage)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:volumes:create')
+ res = self.client.post(url, formData)
+
+ expected_error = [u'A volume of 5000GB cannot be created as you only'
+ ' have 100GB of your quota available.']
+ self.assertEqual(res.context['form'].errors['__all__'], expected_error)
+
+ @test.create_stubs({api: ('tenant_quota_usages', 'volume_snapshot_list')})
+ def test_create_volume_number_over_alloted_quota(self):
+ usage = {'gigabytes': {'available': 100, 'used': 20},
+ 'volumes': {'available': 0}}
+ formData = {'name': u'Too Many...',
+ 'description': u'We have no volumes left!',
+ 'method': u'CreateForm',
+ 'size': 10}
+
+ api.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(usage)
+ api.volume_snapshot_list(IsA(http.HttpRequest)).\
+ AndReturn(self.volume_snapshots.list())
+ api.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(usage)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:volumes:create')
+ res = self.client.post(url, formData)
+
+ expected_error = [u'You are already using all of your available'
+ ' volumes.']
+ self.assertEqual(res.context['form'].errors['__all__'], expected_error)
+
+ @test.create_stubs({api: ('volume_list',
+ 'volume_delete',
+ 'server_list')})
+ def test_delete_volume(self):
+ volume = self.volumes.first()
+ formData = {'action':
+ 'volumes__delete__%s' % volume.id}
+
+ api.volume_list(IsA(http.HttpRequest), search_opts=None).\
+ AndReturn(self.volumes.list())
+ api.volume_delete(IsA(http.HttpRequest), volume.id)
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+ api.volume_list(IsA(http.HttpRequest), search_opts=None).\
+ AndReturn(self.volumes.list())
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:volumes:index')
+ res = self.client.post(url, formData, follow=True)
+ self.assertMessageCount(res, count=0)
+
+ @test.create_stubs({api: ('volume_list',
+ 'volume_delete',
+ 'server_list')})
+ def test_delete_volume_error_existing_snapshot(self):
+ volume = self.volumes.first()
+ formData = {'action':
+ 'volumes__delete__%s' % volume.id}
+ exc = self.exceptions.cinder.__class__(400,
+ "error: dependent snapshots")
+
+ api.volume_list(IsA(http.HttpRequest), search_opts=None).\
+ AndReturn(self.volumes.list())
+ api.volume_delete(IsA(http.HttpRequest), volume.id). \
+ AndRaise(exc)
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+ api.volume_list(IsA(http.HttpRequest), search_opts=None).\
+ AndReturn(self.volumes.list())
+ api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:volumes:index')
+ res = self.client.post(url, formData, follow=True)
+ self.assertMessageCount(res, error=1)
+ self.assertEqual(list(res.context['messages'])[0].message,
+ u'Unable to delete volume "%s". '
+ u'One or more snapshots depend on it.' %
+ volume.display_name)
+
+ @test.create_stubs({api: ('volume_get',), api.nova: ('server_list',)})
+ def test_edit_attachments(self):
+ volume = self.volumes.first()
+ servers = self.servers.list()
+
+ api.volume_get(IsA(http.HttpRequest), volume.id).AndReturn(volume)
+ api.nova.server_list(IsA(http.HttpRequest)).AndReturn(servers)
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:volumes:attach', args=[volume.id])
+ res = self.client.get(url)
+ # Asserting length of 2 accounts for the one instance option,
+ # and the one 'Choose Instance' option.
+ form = res.context['form']
+ self.assertEqual(len(form.fields['instance']._choices),
+ 2)
+ self.assertEqual(res.status_code, 200)
+ self.assertTrue(isinstance(form.fields['device'].widget,
+ widgets.TextInput))
+
+ @test.create_stubs({api: ('volume_get',), api.nova: ('server_list',)})
+ def test_edit_attachments_cannot_set_mount_point(self):
+ PREV = settings.OPENSTACK_HYPERVISOR_FEATURES['can_set_mount_point']
+ settings.OPENSTACK_HYPERVISOR_FEATURES['can_set_mount_point'] = False
+
+ volume = self.volumes.first()
+ servers = self.servers.list()
+
+ api.volume_get(IsA(http.HttpRequest), volume.id).AndReturn(volume)
+ api.nova.server_list(IsA(http.HttpRequest)).AndReturn(servers)
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:volumes:attach', args=[volume.id])
+ res = self.client.get(url)
+ # Assert the device field is hidden.
+ form = res.context['form']
+ self.assertTrue(isinstance(form.fields['device'].widget,
+ widgets.HiddenInput))
+ settings.OPENSTACK_HYPERVISOR_FEATURES['can_set_mount_point'] = PREV
+
+ @test.create_stubs({api: ('volume_get',),
+ api.nova: ('server_get', 'server_list',)})
+ def test_edit_attachments_attached_volume(self):
+ server = self.servers.first()
+ volume = self.volumes.list()[0]
+
+ api.volume_get(IsA(http.HttpRequest), volume.id) \
+ .AndReturn(volume)
+ api.nova.server_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.servers.list())
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:volumes:attach',
+ args=[volume.id])
+ res = self.client.get(url)
+
+ self.assertEqual(res.context['form'].fields['instance']._choices[0][1],
+ "Select an instance")
+ self.assertEqual(len(res.context['form'].fields['instance'].choices),
+ 2)
+ self.assertEqual(res.context['form'].fields['instance']._choices[1][0],
+ server.id)
+ self.assertEqual(res.status_code, 200)
+
+ @test.create_stubs({api.nova: ('volume_get', 'server_get',)})
+ def test_detail_view(self):
+ volume = self.volumes.first()
+ server = self.servers.first()
+
+ volume.attachments = [{"server_id": server.id}]
+
+ api.nova.volume_get(IsA(http.HttpRequest), volume.id).AndReturn(volume)
+ api.nova.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
+
+ self.mox.ReplayAll()
+
+ url = reverse('horizon:project:volumes:detail',
+ args=[volume.id])
+ res = self.client.get(url)
+
+ self.assertContains(res, "<dd>Volume name</dd>", 1, 200)
+ self.assertContains(res,
+ "<dd>41023e92-8008-4c8b-8059-7f2293ff3775</dd>",
+ 1,
+ 200)
+ self.assertContains(res, "<dd>Available</dd>", 1, 200)
+ self.assertContains(res, "<dd>40 GB</dd>", 1, 200)
+ self.assertContains(res,
+ ("<a href=\"/project/instances/1/\">%s</a>"
+ % server.name),
+ 1,
+ 200)
+
+ self.assertNoMessages()
diff --git a/openstack_dashboard/dashboards/project/volumes/urls.py b/openstack_dashboard/dashboards/project/volumes/urls.py
new file mode 100644
index 000000000..06b357255
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/urls.py
@@ -0,0 +1,35 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import patterns, url
+
+from .views import (IndexView, CreateView, EditAttachmentsView, DetailView,
+ CreateSnapshotView)
+
+
+urlpatterns = patterns('openstack_dashboard.dashboards.project.volumes.views',
+ url(r'^$', IndexView.as_view(), name='index'),
+ url(r'^create/$', CreateView.as_view(), name='create'),
+ url(r'^(?P<volume_id>[^/]+)/attach/$',
+ EditAttachmentsView.as_view(),
+ name='attach'),
+ url(r'^(?P<volume_id>[^/]+)/create_snapshot/$',
+ CreateSnapshotView.as_view(),
+ name='create_snapshot'),
+ url(r'^(?P<volume_id>[^/]+)/$',
+ DetailView.as_view(),
+ name='detail'),
+)
diff --git a/openstack_dashboard/dashboards/project/volumes/views.py b/openstack_dashboard/dashboards/project/volumes/views.py
new file mode 100644
index 000000000..6de6ff9e6
--- /dev/null
+++ b/openstack_dashboard/dashboards/project/volumes/views.py
@@ -0,0 +1,184 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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.
+
+"""
+Views for managing volumes.
+"""
+
+import logging
+
+from django.core.urlresolvers import reverse_lazy
+from django.utils.translation import ugettext_lazy as _
+from django.utils.datastructures import SortedDict
+
+from horizon import exceptions
+from horizon import forms
+from horizon import tables
+from horizon import tabs
+
+from openstack_dashboard import api
+from .forms import CreateForm, AttachForm, CreateSnapshotForm
+from .tables import AttachmentsTable, VolumesTable
+from .tabs import VolumeDetailTabs
+
+
+LOG = logging.getLogger(__name__)
+
+
+class IndexView(tables.DataTableView):
+ table_class = VolumesTable
+ template_name = 'project/volumes/index.html'
+
+ def _get_volumes(self, search_opts=None):
+ try:
+ return api.volume_list(self.request, search_opts=search_opts)
+ except:
+ exceptions.handle(self.request,
+ _('Unable to retrieve volume list.'))
+
+ def _get_instances(self):
+ try:
+ return api.server_list(self.request)
+ except:
+ instance_list = []
+ exceptions.handle(self.request,
+ _("Unable to retrieve volume/instance "
+ "attachment information"))
+
+ def _set_id_if_nameless(self, volumes, instances):
+ for volume in volumes:
+ # It is possible to create a volume with no name through the
+ # EC2 API, use the ID in those cases.
+ if not volume.display_name:
+ volume.display_name = volume.id
+
+ def _set_attachments_string(self, volumes, instances):
+ instances = SortedDict([(inst.id, inst) for inst in instances])
+ for volume in volumes:
+ for att in volume.attachments:
+ server_id = att.get('server_id', None)
+ att['instance'] = instances.get(server_id, None)
+
+ def get_data(self):
+ volumes = self._get_volumes()
+ instances = self._get_instances()
+ self._set_id_if_nameless(volumes, instances)
+ self._set_attachments_string(volumes, instances)
+ return volumes
+
+
+class DetailView(tabs.TabView):
+ tab_group_class = VolumeDetailTabs
+ template_name = 'project/volumes/detail.html'
+
+
+class CreateView(forms.ModalFormView):
+ form_class = CreateForm
+ template_name = 'project/volumes/create.html'
+ success_url = reverse_lazy("horizon:project:volumes:index")
+
+ def get_context_data(self, **kwargs):
+ context = super(CreateView, self).get_context_data(**kwargs)
+ try:
+ context['usages'] = api.tenant_quota_usages(self.request)
+ except:
+ exceptions.handle(self.request)
+ return context
+
+
+class CreateSnapshotView(forms.ModalFormView):
+ form_class = CreateSnapshotForm
+ template_name = 'project/volumes/create_snapshot.html'
+ success_url = reverse_lazy("horizon:project:images_and_snapshots:index")
+
+ def get_context_data(self, **kwargs):
+ context = super(CreateSnapshotView, self).get_context_data(**kwargs)
+ context['volume_id'] = self.kwargs['volume_id']
+ return context
+
+ def get_initial(self):
+ return {'volume_id': self.kwargs["volume_id"]}
+
+
+class EditAttachmentsView(tables.DataTableView, forms.ModalFormView):
+ table_class = AttachmentsTable
+ form_class = AttachForm
+ template_name = 'project/volumes/attach.html'
+ success_url = reverse_lazy("horizon:project:volumes:index")
+
+ def get_object(self):
+ if not hasattr(self, "_object"):
+ volume_id = self.kwargs['volume_id']
+ try:
+ self._object = api.volume_get(self.request, volume_id)
+ except:
+ self._object = None
+ exceptions.handle(self.request,
+ _('Unable to retrieve volume information.'))
+ return self._object
+
+ def get_data(self):
+ try:
+ volumes = self.get_object()
+ attachments = [att for att in volumes.attachments if att]
+ except:
+ attachments = []
+ exceptions.handle(self.request,
+ _('Unable to retrieve volume information.'))
+ return attachments
+
+ def get_initial(self):
+ try:
+ instances = api.nova.server_list(self.request)
+ except:
+ instances = []
+ exceptions.handle(self.request,
+ _("Unable to retrieve attachment information."))
+ return {'volume': self.get_object(),
+ 'instances': instances}
+
+ def get_form(self):
+ if not hasattr(self, "_form"):
+ form_class = self.get_form_class()
+ self._form = super(EditAttachmentsView, self).get_form(form_class)
+ return self._form
+
+ def get_context_data(self, **kwargs):
+ context = super(EditAttachmentsView, self).get_context_data(**kwargs)
+ context['form'] = self.get_form()
+ volume = self.get_object()
+ if volume and volume.status == 'available':
+ context['show_attach'] = True
+ else:
+ context['show_attach'] = False
+ context['volume'] = volume
+ if self.request.is_ajax():
+ context['hide'] = True
+ return context
+
+ def get(self, request, *args, **kwargs):
+ # Table action handling
+ handled = self.construct_tables()
+ if handled:
+ return handled
+ return self.render_to_response(self.get_context_data(**kwargs))
+
+ def post(self, request, *args, **kwargs):
+ form = self.get_form()
+ if form.is_valid():
+ return self.form_valid(form)
+ else:
+ return self.get(request, *args, **kwargs)
diff --git a/openstack_dashboard/dashboards/settings/__init__.py b/openstack_dashboard/dashboards/settings/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/__init__.py
diff --git a/openstack_dashboard/dashboards/settings/dashboard.py b/openstack_dashboard/dashboards/settings/dashboard.py
new file mode 100644
index 000000000..3a2a5a379
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/dashboard.py
@@ -0,0 +1,31 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Openstack, LLC
+# Copyright 2012 Nebula, Inc.
+#
+# 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
+
+
+class Settings(horizon.Dashboard):
+ name = _("Settings")
+ slug = "settings"
+ panels = ('user', 'project', 'ec2')
+ default_panel = 'user'
+ nav = False
+
+
+horizon.register(Settings)
diff --git a/openstack_dashboard/dashboards/settings/ec2/__init__.py b/openstack_dashboard/dashboards/settings/ec2/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/ec2/__init__.py
diff --git a/openstack_dashboard/dashboards/settings/ec2/forms.py b/openstack_dashboard/dashboards/settings/ec2/forms.py
new file mode 100644
index 000000000..14ca1501b
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/ec2/forms.py
@@ -0,0 +1,110 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Openstack, LLC
+#
+# 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 logging
+import tempfile
+import zipfile
+from contextlib import closing
+
+from django import http
+from django.template.loader import render_to_string
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import exceptions
+from horizon import forms
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class DownloadX509Credentials(forms.SelfHandlingForm):
+ tenant = forms.ChoiceField(label=_("Select a Project"))
+
+ def __init__(self, request, *args, **kwargs):
+ super(DownloadX509Credentials, self).__init__(request, *args, **kwargs)
+ # Populate tenant choices
+ tenant_choices = []
+ try:
+ tenant_list = api.keystone.tenant_list(request)
+ except:
+ tenant_list = []
+ exceptions.handle(request, _("Unable to retrieve tenant list."))
+
+ for tenant in tenant_list:
+ if tenant.enabled:
+ tenant_choices.append((tenant.id, tenant.name))
+ if not tenant_choices:
+ self.fields['tenant'].choices = [('', 'No Available Tenants')]
+ else:
+ self.fields['tenant'].choices = tenant_choices
+
+ def handle(self, request, data):
+ def find_or_create_access_keys(request, tenant_id):
+ keys = api.keystone.list_ec2_credentials(request, request.user.id)
+ for key in keys:
+ if key.tenant_id == tenant_id:
+ return key
+ return api.keystone.create_ec2_credentials(request,
+ request.user.id,
+ tenant_id)
+ try:
+ # NOTE(jakedahn): Keystone errors unless we specifically scope
+ # the token to tenant before making the call.
+ api.keystone.token_create_scoped(request,
+ data.get('tenant'),
+ request.user.token.id)
+ credentials = api.nova.get_x509_credentials(request)
+ cacert = api.nova.get_x509_root_certificate(request)
+ keys = find_or_create_access_keys(request, data.get('tenant'))
+ context = {'ec2_access_key': keys.access,
+ 'ec2_secret_key': keys.secret,
+ 'ec2_endpoint': api.url_for(request,
+ 'ec2',
+ endpoint_type='publicURL')}
+ try:
+ s3_endpoint = api.url_for(request,
+ 's3',
+ endpoint_type='publicURL')
+ except exceptions.ServiceCatalogException:
+ s3_endpoint = None
+ context['s3_endpoint'] = s3_endpoint
+ except:
+ exceptions.handle(request,
+ _('Unable to fetch EC2 credentials.'),
+ redirect=request.build_absolute_uri())
+
+ try:
+ temp_zip = tempfile.NamedTemporaryFile(delete=True)
+ with closing(zipfile.ZipFile(temp_zip.name, mode='w')) as archive:
+ archive.writestr('pk.pem', credentials.private_key)
+ archive.writestr('cert.pem', credentials.data)
+ archive.writestr('cacert.pem', cacert.data)
+ archive.writestr('ec2rc.sh', render_to_string(
+ 'settings/ec2/ec2rc.sh.template', context))
+ except:
+ exceptions.handle(request,
+ _('Error writing zipfile: %(exc)s'),
+ redirect=request.build_absolute_uri())
+
+ response = http.HttpResponse(mimetype='application/zip')
+ response.write(temp_zip.read())
+ response['Content-Disposition'] = 'attachment; \
+ filename=%s-x509.zip' \
+ % data.get('tenant')
+ response['Content-Length'] = temp_zip.tell()
+ return response
diff --git a/openstack_dashboard/dashboards/settings/ec2/panel.py b/openstack_dashboard/dashboards/settings/ec2/panel.py
new file mode 100644
index 000000000..9e1fe1cbd
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/ec2/panel.py
@@ -0,0 +1,29 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Openstack, LLC
+#
+# 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.settings import dashboard
+
+
+class EC2Panel(horizon.Panel):
+ name = _("EC2 Credentials")
+ slug = 'ec2'
+
+
+dashboard.Settings.register(EC2Panel)
diff --git a/openstack_dashboard/dashboards/settings/ec2/templates/ec2/download_form.html b/openstack_dashboard/dashboards/settings/ec2/templates/ec2/download_form.html
new file mode 100644
index 000000000..05c427a7c
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/ec2/templates/ec2/download_form.html
@@ -0,0 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}x509_download_form{% endblock %}
+{% block form_action %}{% url horizon:settings:ec2:index %}{% endblock %}
+
+{% block modal_id %}x509_download_modal{% endblock %}
+{% block modal-header %}{% trans "Download EC2 Credentials" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description:" %}</h3>
+ <p>{% trans 'Clicking "Download EC2 Credentials" will download a zip file which includes an rc file with your access/secret keys, as well as your x509 private key and certificate.' %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <input class="btn btn-primary pull-right always-enabled" type="submit" value="{% trans "Download EC2 Credentials" %}" />
+ {% if hide %}<a href="{% url horizon:settings:ec2:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>{% endif %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/settings/ec2/templates/ec2/ec2rc.sh.template b/openstack_dashboard/dashboards/settings/ec2/templates/ec2/ec2rc.sh.template
new file mode 100644
index 000000000..0b6f7e273
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/ec2/templates/ec2/ec2rc.sh.template
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+NOVARC=$(readlink -f "${BASH_SOURCE:-${0}}" 2>/dev/null) || NOVARC=$(python -c 'import os,sys; print os.path.abspath(os.path.realpath(sys.argv[1]))' "${BASH_SOURCE:-${0}}")
+NOVA_KEY_DIR=${NOVARC%/*}
+export EC2_ACCESS_KEY={{ ec2_access_key }}
+export EC2_SECRET_KEY={{ ec2_secret_key }}
+export EC2_URL={{ ec2_endpoint }}
+export EC2_USER_ID=42 # nova does not use user id, but bundling requires it
+export EC2_PRIVATE_KEY=${NOVA_KEY_DIR}/pk.pem
+export EC2_CERT=${NOVA_KEY_DIR}/cert.pem
+export NOVA_CERT=${NOVA_KEY_DIR}/cacert.pem
+export EUCALYPTUS_CERT=${NOVA_CERT} # euca-bundle-image seems to require this set
+{% if s3_endpoint %}export S3_URL={{ s3_endpoint }}{% endif %}
+alias ec2-bundle-image="ec2-bundle-image --cert ${EC2_CERT} --privatekey ${EC2_PRIVATE_KEY} --user 42 --ec2cert ${NOVA_CERT}"
+alias ec2-upload-bundle="ec2-upload-bundle -a ${EC2_ACCESS_KEY} -s ${EC2_SECRET_KEY} --url ${S3_URL} --ec2cert ${NOVA_CERT}"
diff --git a/openstack_dashboard/dashboards/settings/ec2/templates/ec2/index.html b/openstack_dashboard/dashboards/settings/ec2/templates/ec2/index.html
new file mode 100644
index 000000000..c404d3507
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/ec2/templates/ec2/index.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Download EC2 Credentials" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Download EC2 Credentials") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include "settings/ec2/download_form.html" %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/settings/ec2/tests.py b/openstack_dashboard/dashboards/settings/ec2/tests.py
new file mode 100644
index 000000000..5f9206e86
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/ec2/tests.py
@@ -0,0 +1,70 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula Inc
+#
+# 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.http import HttpRequest
+from django.core.urlresolvers import reverse
+
+from mox import IsA
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+from .forms import DownloadX509Credentials
+
+
+INDEX_URL = reverse("horizon:settings:ec2:index")
+
+
+class EC2SettingsTest(test.TestCase):
+ def test_ec2_download_view(self):
+ creds = self.ec2.first()
+ cert = self.certs.first()
+
+ self.mox.StubOutWithMock(api.keystone, "tenant_list")
+ self.mox.StubOutWithMock(api.keystone, "token_create_scoped")
+ self.mox.StubOutWithMock(api.keystone, "list_ec2_credentials")
+ self.mox.StubOutWithMock(api.nova, "get_x509_credentials")
+ self.mox.StubOutWithMock(api.nova, "get_x509_root_certificate")
+ self.mox.StubOutWithMock(api.keystone, "create_ec2_credentials")
+
+ # GET request
+ api.keystone.tenant_list(IsA(HttpRequest)) \
+ .AndReturn(self.tenants.list())
+
+ # POST request
+ api.keystone.token_create_scoped(IsA(HttpRequest),
+ self.tenant.id,
+ IsA(str)) \
+ .AndReturn(self.tokens.scoped_token)
+ api.keystone.tenant_list(IsA(HttpRequest)) \
+ .AndReturn(self.tenants.list())
+ api.keystone.list_ec2_credentials(IsA(HttpRequest), self.user.id) \
+ .AndReturn([])
+ api.nova.get_x509_credentials(IsA(HttpRequest)).AndReturn(cert)
+ api.nova.get_x509_root_certificate(IsA(HttpRequest)) \
+ .AndReturn(cert)
+ api.keystone.create_ec2_credentials(IsA(HttpRequest),
+ self.user.id,
+ self.tenant.id).AndReturn(creds)
+ self.mox.ReplayAll()
+
+ res = self.client.get(INDEX_URL)
+ self.assertNoMessages()
+ self.assertEqual(res.status_code, 200)
+
+ data = {'method': DownloadX509Credentials.__name__,
+ 'tenant': self.tenant.id}
+ res = self.client.post(INDEX_URL, data)
+ self.assertEqual(res['content-type'], 'application/zip')
diff --git a/openstack_dashboard/dashboards/settings/ec2/urls.py b/openstack_dashboard/dashboards/settings/ec2/urls.py
new file mode 100644
index 000000000..5ac6c8128
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/ec2/urls.py
@@ -0,0 +1,23 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Openstack, LLC
+#
+# 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.defaults import patterns, url
+
+from .views import IndexView
+
+urlpatterns = patterns('openstack_dashboard.dashboards.settings.ec2.views',
+ url(r'^$', IndexView.as_view(), name='index'),
+)
diff --git a/openstack_dashboard/dashboards/settings/ec2/views.py b/openstack_dashboard/dashboards/settings/ec2/views.py
new file mode 100644
index 000000000..e76188aaa
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/ec2/views.py
@@ -0,0 +1,32 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Openstack, LLC
+#
+# 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 logging
+
+from horizon import forms
+
+from .forms import DownloadX509Credentials
+
+
+LOG = logging.getLogger(__name__)
+
+
+class IndexView(forms.ModalFormView):
+ form_class = DownloadX509Credentials
+ template_name = 'settings/ec2/index.html'
+
+ def form_valid(self, form):
+ return form.handle(self.request, form.cleaned_data)
diff --git a/openstack_dashboard/dashboards/settings/models.py b/openstack_dashboard/dashboards/settings/models.py
new file mode 100644
index 000000000..6313a32fa
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/models.py
@@ -0,0 +1,23 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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.
+
+"""
+Stub file to work around django bug: https://code.djangoproject.com/ticket/7198
+"""
diff --git a/openstack_dashboard/dashboards/settings/project/__init__.py b/openstack_dashboard/dashboards/settings/project/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/project/__init__.py
diff --git a/openstack_dashboard/dashboards/settings/project/forms.py b/openstack_dashboard/dashboards/settings/project/forms.py
new file mode 100644
index 000000000..40adcb114
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/project/forms.py
@@ -0,0 +1,72 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 logging
+
+from django import shortcuts
+from django.utils.translation import ugettext_lazy as _
+
+from horizon import forms
+from horizon import messages
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+class DownloadOpenRCForm(forms.SelfHandlingForm):
+ tenant = forms.ChoiceField(label=_("Select a Project"))
+
+ def __init__(self, request, *args, **kwargs):
+ super(DownloadOpenRCForm, self).__init__(request, *args, **kwargs)
+ # Populate tenant choices
+ tenant_choices = []
+ for tenant in api.tenant_list(request):
+ if tenant.enabled:
+ tenant_choices.append((tenant.id, tenant.name))
+ self.fields['tenant'].choices = tenant_choices
+
+ def handle(self, request, data):
+ try:
+ tenant_id = data['tenant']
+ tenant_name = dict(self.fields['tenant'].choices)[tenant_id]
+
+ keystone_url = api.url_for(request,
+ 'identity',
+ endpoint_type='publicURL')
+
+ context = {'user': request.user,
+ 'auth_url': keystone_url,
+ 'tenant_id': tenant_id,
+ 'tenant_name': tenant_name}
+
+ response = shortcuts.render(request,
+ 'settings/project/openrc.sh.template',
+ context,
+ content_type="text/plain")
+ response['Content-Disposition'] = 'attachment; filename=openrc.sh'
+ response['Content-Length'] = str(len(response.content))
+ return response
+
+ except Exception, e:
+ LOG.exception("Exception in DownloadOpenRCForm.")
+ messages.error(request, _('Error Downloading RC File: %s') % e)
+ return shortcuts.redirect(request.build_absolute_uri())
diff --git a/openstack_dashboard/dashboards/settings/project/panel.py b/openstack_dashboard/dashboards/settings/project/panel.py
new file mode 100644
index 000000000..99dcea56a
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/project/panel.py
@@ -0,0 +1,29 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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.settings import dashboard
+
+
+class TenantPanel(horizon.Panel):
+ name = _("OpenStack API")
+ slug = 'project'
+
+
+dashboard.Settings.register(TenantPanel)
diff --git a/openstack_dashboard/dashboards/settings/project/tables.py b/openstack_dashboard/dashboards/settings/project/tables.py
new file mode 100644
index 000000000..48abd8d51
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/project/tables.py
@@ -0,0 +1,33 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 as _
+
+from horizon import tables
+
+
+def get_endpoint(service):
+ return service.endpoints[0]['publicURL']
+
+
+class EndpointsTable(tables.DataTable):
+ api_name = tables.Column('name', verbose_name=_("Service Name"))
+ api_endpoint = tables.Column(get_endpoint,
+ verbose_name=_("Service Endpoint"))
+
+ class Meta:
+ name = "endpoints"
+ verbose_name = _("API Endpoints")
diff --git a/openstack_dashboard/dashboards/settings/project/templates/project/_openrc.html b/openstack_dashboard/dashboards/settings/project/templates/project/_openrc.html
new file mode 100644
index 000000000..039d641fa
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/project/templates/project/_openrc.html
@@ -0,0 +1,32 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}openrc_download_form{% endblock %}
+{% block form_action %}{% url horizon:settings:project:index %}{% endblock %}
+
+{% block modal_id %}language_settings_modal{% endblock %}
+{% block modal-header %}{% trans "OpenStack API" %}{% endblock %}
+
+{% block modal-body %}
+<div>
+ {{ endpoints.render }}
+</div>
+<div>
+ <h3>{% trans "Download OpenStack RC File" %}</h3>
+ <hr />
+</div>
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description:" %}</h3>
+ <p>{% trans 'Download the RC file for the selected project, then type "source openrc" in the terminal to configure your environment to communicate with OpenStack.' %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <button class="btn btn-primary pull-right always-enabled" type="submit">{% trans "Download RC File" %}</button>
+ {% if hide %}<a href="{% url horizon:settings:project:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>{% endif %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/settings/project/templates/project/openrc.sh.template b/openstack_dashboard/dashboards/settings/project/templates/project/openrc.sh.template
new file mode 100644
index 000000000..d1733eb7f
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/project/templates/project/openrc.sh.template
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# With the addition of Keystone, to use an openstack cloud you should
+# authenticate against keystone, which returns a **Token** and **Service
+# Catalog**. The catalog contains the endpoint for all services the
+# user/tenant has access to - including nova, glance, keystone, swift.
+#
+# *NOTE*: Using the 2.0 *auth api* does not mean that compute api is 2.0. We
+# will use the 1.1 *compute api*
+export OS_AUTH_URL={{ auth_url }}
+
+# With the addition of Keystone we have standardized on the term **tenant**
+# as the entity that owns the resources.
+export OS_TENANT_ID={{ tenant_id }}
+export OS_TENANT_NAME="{{ tenant_name }}"
+
+# In addition to the owning entity (tenant), openstack stores the entity
+# performing the action as the **user**.
+export OS_USERNAME={{ user.username }}
+
+# With Keystone you pass the keystone password.
+echo "Please enter your OpenStack Password: "
+read -s OS_PASSWORD_INPUT
+export OS_PASSWORD=$OS_PASSWORD_INPUT
diff --git a/openstack_dashboard/dashboards/settings/project/templates/project/settings.html b/openstack_dashboard/dashboards/settings/project/templates/project/settings.html
new file mode 100644
index 000000000..00b28136d
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/project/templates/project/settings.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "OpenStack API" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("OpenStack API") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include "settings/project/_openrc.html" %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/settings/project/urls.py b/openstack_dashboard/dashboards/settings/project/urls.py
new file mode 100644
index 000000000..d418e883d
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/project/urls.py
@@ -0,0 +1,23 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import patterns, url
+
+from .views import OpenRCView
+
+
+urlpatterns = patterns('',
+ url(r'^$', OpenRCView.as_view(), name='index'))
diff --git a/openstack_dashboard/dashboards/settings/project/views.py b/openstack_dashboard/dashboards/settings/project/views.py
new file mode 100644
index 000000000..4722d2652
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/project/views.py
@@ -0,0 +1,44 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 horizon.forms import ModalFormView
+
+from openstack_dashboard.api import keystone
+from .forms import DownloadOpenRCForm
+from .tables import EndpointsTable
+
+
+class OpenRCView(ModalFormView):
+ form_class = DownloadOpenRCForm
+ template_name = 'settings/project/settings.html'
+
+ def get_data(self):
+ services = []
+ for i, service in enumerate(self.request.user.service_catalog):
+ service['id'] = i
+ services.append(keystone.Service(service))
+ return services
+
+ def get_context_data(self, **kwargs):
+ context = super(OpenRCView, self).get_context_data(**kwargs)
+ context["endpoints"] = EndpointsTable(self.request, self.get_data())
+ return context
+
+ def get_initial(self):
+ return {'tenant': self.request.user.tenant_id}
+
+ def form_valid(self, form):
+ return form.handle(self.request, form.cleaned_data)
diff --git a/openstack_dashboard/dashboards/settings/user/__init__.py b/openstack_dashboard/dashboards/settings/user/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/user/__init__.py
diff --git a/openstack_dashboard/dashboards/settings/user/forms.py b/openstack_dashboard/dashboards/settings/user/forms.py
new file mode 100644
index 000000000..e94c31182
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/user/forms.py
@@ -0,0 +1,59 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 pytz
+
+from django import shortcuts
+from django.conf import settings
+from django.utils import translation
+
+from horizon import forms
+from horizon import messages
+
+
+class UserSettingsForm(forms.SelfHandlingForm):
+ language = forms.ChoiceField()
+ timezone = forms.ChoiceField()
+
+ def __init__(self, *args, **kwargs):
+ super(UserSettingsForm, self).__init__(*args, **kwargs)
+
+ # Languages
+ languages = [(k, "%s (%s)"
+ % (translation.get_language_info(k)['name_local'], k))
+ for k, v in settings.LANGUAGES]
+ self.fields['language'].choices = languages
+
+ # Timezones
+ timezones = [(tz, tz) for tz in pytz.common_timezones]
+ self.fields['timezone'].choices = timezones
+
+ def handle(self, request, data):
+ response = shortcuts.redirect(request.build_absolute_uri())
+ # Language
+ lang_code = data['language']
+ if lang_code and translation.check_for_language(lang_code):
+ if hasattr(request, 'session'):
+ request.session['django_language'] = lang_code
+ else:
+ response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code)
+
+ # Timezone
+ request.session['django_timezone'] = pytz.timezone(data['timezone'])
+
+ messages.success(request, translation.ugettext("Settings saved."))
+
+ return response
diff --git a/openstack_dashboard/dashboards/settings/user/panel.py b/openstack_dashboard/dashboards/settings/user/panel.py
new file mode 100644
index 000000000..635fe321b
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/user/panel.py
@@ -0,0 +1,29 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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.settings import dashboard
+
+
+class UserPanel(horizon.Panel):
+ name = _("User Settings")
+ slug = 'user'
+
+
+dashboard.Settings.register(UserPanel)
diff --git a/openstack_dashboard/dashboards/settings/user/templates/user/_settings.html b/openstack_dashboard/dashboards/settings/user/templates/user/_settings.html
new file mode 100644
index 000000000..1e2eebef2
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/user/templates/user/_settings.html
@@ -0,0 +1,26 @@
+{% extends "horizon/common/_modal_form.html" %}
+{% load i18n %}
+
+{% block form_id %}user_settings_modal{% endblock %}
+{% block form_action %}{% url horizon:settings:user:index %}{% endblock %}
+
+{% block modal_id %}user_settings_modal{% endblock %}
+{% block modal-header %}{% trans "User Settings" %}{% endblock %}
+
+{% block modal-body %}
+<div class="left">
+ <fieldset>
+ {% include "horizon/common/_form_fields.html" %}
+ </fieldset>
+</div>
+<div class="right">
+ <h3>{% trans "Description:" %}</h3>
+ <p>{% trans "From here you can modify dashboard settings for your user." %}</p>
+</div>
+{% endblock %}
+
+{% block modal-footer %}
+ <button type="submit" class="btn btn-primary">{% trans "Save" %}</button>
+ {% if hide %}<a href="{% url horizon:settings:user:index %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>{% endif %}
+{% endblock %}
+
diff --git a/openstack_dashboard/dashboards/settings/user/templates/user/settings.html b/openstack_dashboard/dashboards/settings/user/templates/user/settings.html
new file mode 100644
index 000000000..0f68caeee
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/user/templates/user/settings.html
@@ -0,0 +1,11 @@
+{% extends 'base.html' %}
+{% load i18n %}
+{% block title %}{% trans "User Settings" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("User Settings") %}
+{% endblock page_header %}
+
+{% block main %}
+ {% include "settings/user/_settings.html" %}
+{% endblock %}
diff --git a/openstack_dashboard/dashboards/settings/user/urls.py b/openstack_dashboard/dashboards/settings/user/urls.py
new file mode 100644
index 000000000..ba5de426f
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/user/urls.py
@@ -0,0 +1,23 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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.defaults import patterns, url
+
+from .views import UserSettingsView
+
+
+urlpatterns = patterns('',
+ url(r'^$', UserSettingsView.as_view(), name='index'))
diff --git a/openstack_dashboard/dashboards/settings/user/views.py b/openstack_dashboard/dashboards/settings/user/views.py
new file mode 100644
index 000000000..faa2c4abb
--- /dev/null
+++ b/openstack_dashboard/dashboards/settings/user/views.py
@@ -0,0 +1,31 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 horizon import forms
+
+from .forms import UserSettingsForm
+
+
+class UserSettingsView(forms.ModalFormView):
+ form_class = UserSettingsForm
+ template_name = 'settings/user/settings.html'
+
+ def get_initial(self):
+ return {'language': self.request.LANGUAGE_CODE,
+ 'timezone': self.request.session.get('django_timezone', 'UTC')}
+
+ def form_valid(self, form):
+ return form.handle(self.request, form.cleaned_data)
diff --git a/openstack_dashboard/locale/bg_BG/LC_MESSAGES/django.mo b/openstack_dashboard/locale/bg_BG/LC_MESSAGES/django.mo
index 92656364f..1c43023e4 100644
--- a/openstack_dashboard/locale/bg_BG/LC_MESSAGES/django.mo
+++ b/openstack_dashboard/locale/bg_BG/LC_MESSAGES/django.mo
Binary files differ
diff --git a/openstack_dashboard/locale/bg_BG/LC_MESSAGES/django.po b/openstack_dashboard/locale/bg_BG/LC_MESSAGES/django.po
index e4597b1ff..f4bb34d2a 100644
--- a/openstack_dashboard/locale/bg_BG/LC_MESSAGES/django.po
+++ b/openstack_dashboard/locale/bg_BG/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Horizon\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-09-18 22:18+0000\n"
+"POT-Creation-Date: 2012-10-05 19:30+0000\n"
"PO-Revision-Date: 2012-08-14 08:40+0000\n"
"Last-Translator: Dimitar Dimitrov <dimitrov@linuxmail.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,63 +18,3236 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: settings.py:141
+#: settings.py:142
msgid "Bulgarian (Bulgaria)"
msgstr ""
-#: settings.py:142
+#: settings.py:143
msgid "Czech"
msgstr ""
-#: settings.py:143
+#: settings.py:144
msgid "English"
msgstr "Английски"
-#: settings.py:144
+#: settings.py:145
msgid "Spanish"
msgstr "Испански"
-#: settings.py:145
+#: settings.py:146
msgid "French"
msgstr "Френски"
-#: settings.py:146
+#: settings.py:147
msgid "Italiano"
msgstr "Италиански"
-#: settings.py:147
+#: settings.py:148
msgid "Japanese"
msgstr "Японски"
-#: settings.py:148
+#: settings.py:149
msgid "Korean (Korea)"
msgstr ""
-#: settings.py:149
+#: settings.py:150
msgid "Dutch (Netherlands)"
msgstr ""
-#: settings.py:150
+#: settings.py:151
msgid "Polish"
msgstr "Полски"
-#: settings.py:151
+#: settings.py:152
msgid "Portuguese"
msgstr "Португалски"
-#: settings.py:152
+#: settings.py:153
#, fuzzy
msgid "Portuguese (Brazil)"
msgstr "Португалски"
-#: settings.py:153
+#: settings.py:154
msgid "Simplified Chinese"
msgstr "Опростен китайски"
-#: settings.py:154
+#: settings.py:155
msgid "Traditional Chinese"
msgstr "Традиционен китайски"
+#: api/keystone.py:56
+#, python-format
+msgid "%(type)s (%(backend)s backend)"
+msgstr "%(type)s (%(backend)s backend)"
+
+#: api/nova.py:191
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(group)s"
+msgstr "ALLOW %(from)s:%(to)s от %(group)s"
+
+#: api/nova.py:196
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(cidr)s"
+msgstr "ALLOW %(from)s:%(to)s от %(cidr)s"
+
+#: api/nova.py:532
+msgid "Unknown instance"
+msgstr ""
+
+#: api/swift.py:217
+msgid "Unicode is not currently supported for object copy."
+msgstr ""
+
+#: dashboards/admin/dashboard.py:24
+msgid "System Panel"
+msgstr "Системен панел"
+
+#: dashboards/admin/dashboard.py:30
+msgid "Admin"
+msgstr "Админ"
+
+#: dashboards/admin/flavors/forms.py:36 dashboards/admin/networks/forms.py:34
+#: dashboards/admin/networks/forms.py:69
+#: dashboards/admin/networks/ports/forms.py:40
+#: dashboards/admin/networks/ports/forms.py:72
+#: dashboards/admin/networks/ports/tables.py:73
+#: dashboards/admin/networks/subnets/tables.py:70
+#: dashboards/admin/projects/tables.py:87
+#: dashboards/admin/projects/workflows.py:71
+#: dashboards/admin/services/tables.py:38
+#: dashboards/admin/volumes/tables.py:10
+#: dashboards/project/access_and_security/security_groups/forms.py:36
+#: dashboards/project/access_and_security/security_groups/tables.py:58
+#: dashboards/project/images_and_snapshots/images/forms.py:40
+#: dashboards/project/images_and_snapshots/images/forms.py:115
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:9
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:10
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:77
+#: dashboards/project/instances/templates/instances/_detail_overview.html:9
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:9
+#: dashboards/project/networks/forms.py:37
+#: dashboards/project/networks/tables.py:94
+#: dashboards/project/networks/ports/tables.py:40
+#: dashboards/project/networks/subnets/forms.py:43
+#: dashboards/project/networks/subnets/forms.py:102
+#: dashboards/project/networks/subnets/tables.py:82
+#: dashboards/project/networks/templates/networks/_detail_overview.html:7
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:9
+#: dashboards/project/volumes/tables.py:144
+#: dashboards/project/volumes/tables.py:164
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:9
+msgid "Name"
+msgstr "Име"
+
+#: dashboards/admin/flavors/forms.py:37 dashboards/admin/flavors/tables.py:41
+#: dashboards/admin/projects/workflows.py:39
+#: dashboards/project/instances/templates/instances/_detail_overview.html:26
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:10
+#: usage/tables.py:19
+msgid "VCPUs"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:38
+msgid "RAM MB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:39
+msgid "Root Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:40
+msgid "Ephemeral Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:50
+msgid "Unable to get unique ID for new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:67
+#, python-format
+msgid "Created flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:71
+msgid "Unable to create flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:92
+#, python-format
+msgid "Updated flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:96
+msgid "Unable to update flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/panel.py:29 dashboards/admin/flavors/tables.py:15
+#: dashboards/admin/flavors/tables.py:52
+#: dashboards/admin/flavors/templates/flavors/index.html:3
+#: dashboards/admin/flavors/templates/flavors/index.html:6
+msgid "Flavors"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:14
+#: dashboards/project/instances/workflows.py:177
+#: dashboards/project/instances/templates/instances/_detail_overview.html:22
+msgid "Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:23
+#: dashboards/admin/flavors/templates/flavors/_create.html:8
+#: dashboards/admin/flavors/templates/flavors/_create.html:23
+#: dashboards/admin/flavors/templates/flavors/create.html:3
+#: dashboards/admin/flavors/templates/flavors/create.html:6
+msgid "Create Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:30
+#: dashboards/admin/flavors/templates/flavors/_edit.html:8
+#: dashboards/admin/flavors/templates/flavors/edit.html:3
+#: dashboards/admin/flavors/templates/flavors/edit.html:6
+msgid "Edit Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:36
+#, python-format
+msgid "%sMB"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:40
+msgid "Flavor Name"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:43
+#: dashboards/project/instances/templates/instances/_detail_overview.html:24
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: usage/tables.py:22
+msgid "RAM"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:45
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+msgid "Root Disk"
+msgstr "Основен диск"
+
+#: dashboards/admin/flavors/tables.py:47
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+msgid "Ephemeral Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:49
+msgid "Unable to retrieve flavor list."
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:76
+msgid "Unable to retrieve flavor data."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:17
+#: dashboards/admin/flavors/templates/flavors/_edit.html:17
+#: dashboards/admin/images/templates/images/_update.html:17
+#: dashboards/admin/networks/templates/networks/_create.html:17
+#: dashboards/admin/networks/templates/networks/ports/_create.html:17
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:17
+#: dashboards/admin/projects/tables.py:89
+#: dashboards/admin/projects/workflows.py:74
+#: dashboards/admin/projects/templates/projects/_add_user.html:17
+#: dashboards/admin/projects/templates/projects/_create.html:17
+#: dashboards/admin/projects/templates/projects/_create_user.html:17
+#: dashboards/admin/projects/templates/projects/_quotas.html:16
+#: dashboards/admin/projects/templates/projects/_update.html:17
+#: dashboards/admin/users/templates/users/_create.html:16
+#: dashboards/admin/users/templates/users/_update.html:16
+#: dashboards/project/access_and_security/security_groups/forms.py:38
+#: dashboards/project/access_and_security/security_groups/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:17
+#: dashboards/project/containers/templates/containers/_copy.html:16
+#: dashboards/project/containers/templates/containers/_create.html:16
+#: dashboards/project/containers/templates/containers/_upload.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/_create.html:16
+#: dashboards/project/networks/templates/networks/subnets/_create.html:17
+#: dashboards/project/volumes/forms.py:28
+#: dashboards/project/volumes/forms.py:195
+#: dashboards/project/volumes/tables.py:147
+#: dashboards/project/volumes/templates/volumes/_create.html:18
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:17
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:14
+msgid "Description"
+msgstr "Описание"
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:18
+msgid "From here you can define the sizing of a new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:24
+#: dashboards/admin/flavors/templates/flavors/_edit.html:25
+#: dashboards/admin/images/templates/images/_update.html:24
+#: dashboards/admin/networks/templates/networks/_create.html:24
+#: dashboards/admin/networks/templates/networks/_update.html:23
+#: dashboards/admin/networks/templates/networks/ports/_create.html:24
+#: dashboards/admin/networks/templates/networks/ports/_update.html:28
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:24
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:32
+#: dashboards/admin/projects/templates/projects/_add_user.html:24
+#: dashboards/admin/projects/templates/projects/_create.html:24
+#: dashboards/admin/projects/templates/projects/_create_user.html:24
+#: dashboards/admin/projects/templates/projects/_quotas.html:23
+#: dashboards/admin/projects/templates/projects/_update.html:24
+#: dashboards/admin/users/templates/users/_create.html:23
+#: dashboards/admin/users/templates/users/_update.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:32
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:20
+#: dashboards/project/containers/templates/containers/_copy.html:23
+#: dashboards/project/containers/templates/containers/_create.html:23
+#: dashboards/project/containers/templates/containers/_upload.html:24
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:32
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:24
+#: dashboards/project/instances/templates/instances/_update.html:23
+#: dashboards/project/networks/templates/networks/_create.html:23
+#: dashboards/project/networks/templates/networks/_update.html:23
+#: dashboards/project/networks/templates/networks/subnets/_create.html:24
+#: dashboards/project/networks/templates/networks/subnets/_update.html:32
+#: dashboards/project/volumes/templates/volumes/_attach.html:24
+#: dashboards/project/volumes/templates/volumes/_create.html:56
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:24
+#: dashboards/settings/ec2/templates/ec2/download_form.html:24
+#: dashboards/settings/project/templates/project/_openrc.html:31
+#: dashboards/settings/user/templates/user/_settings.html:24
+msgid "Cancel"
+msgstr "Откажи"
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:18
+msgid "From here you can alter the sizing of the current flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:19
+msgid ""
+"Note: this will not affect the resources allocated to any existing instances "
+"using this flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:24
+#: dashboards/admin/projects/workflows.py:270
+#: dashboards/settings/user/templates/user/_settings.html:23
+msgid "Save"
+msgstr "Запазване"
+
+#: dashboards/admin/images/panel.py:29 dashboards/admin/images/tables.py:44
+#: dashboards/admin/images/templates/images/index.html:3
+#: dashboards/admin/images/templates/images/index.html:6
+#: dashboards/project/images_and_snapshots/images/tables.py:47
+#: dashboards/project/images_and_snapshots/images/tables.py:132
+msgid "Images"
+msgstr ""
+
+#: dashboards/admin/images/tables.py:40
+#: dashboards/project/images_and_snapshots/images/tables.py:113
+#: dashboards/project/instances/templates/instances/_detail_overview.html:74
+msgid "Image Name"
+msgstr ""
+
+#: dashboards/admin/images/views.py:55
+msgid "Unable to retrieve image list."
+msgstr ""
+
+#: dashboards/admin/images/templates/images/_update.html:8
+#: dashboards/admin/images/templates/images/_update.html:23
+#: dashboards/admin/images/templates/images/update.html:4
+#: dashboards/admin/images/templates/images/update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:22
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:6
+msgid "Update Image"
+msgstr ""
+
+#: dashboards/admin/images/templates/images/_update.html:18
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:17
+msgid "From here you can modify different properties of an image."
+msgstr ""
+
+#: dashboards/admin/instances/panel.py:29
+#: dashboards/admin/instances/tables.py:94
+#: dashboards/admin/instances/templates/instances/index.html:3
+#: dashboards/admin/projects/workflows.py:40
+#: dashboards/project/instances/panel.py:25
+#: dashboards/project/instances/tables.py:70
+#: dashboards/project/instances/tables.py:90
+#: dashboards/project/instances/tables.py:107
+#: dashboards/project/instances/tables.py:136
+#: dashboards/project/instances/tables.py:313
+#: dashboards/project/instances/templates/instances/index.html:3
+#: dashboards/project/instances/templates/instances/index.html:6
+msgid "Instances"
+msgstr "Инстанции"
+
+#: dashboards/admin/instances/tables.py:60 usage/tables.py:30
+msgid "Project Name"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:67
+#: dashboards/admin/services/tables.py:40
+msgid "Host"
+msgstr "Хост"
+
+#: dashboards/admin/instances/tables.py:71
+#: dashboards/project/instances/tables.py:290
+#: dashboards/project/instances/workflows.py:176 usage/tables.py:57
+msgid "Instance Name"
+msgstr "Име на инстанция"
+
+#: dashboards/admin/instances/tables.py:72
+#: dashboards/project/access_and_security/floating_ips/tables.py:111
+#: dashboards/project/access_and_security/floating_ips/workflows.py:32
+#: dashboards/project/access_and_security/floating_ips/workflows.py:39
+#: dashboards/project/instances/tables.py:291
+msgid "IP Address"
+msgstr "IP адрес"
+
+#: dashboards/admin/instances/tables.py:74
+#: dashboards/project/containers/tables.py:256
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:30
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:37
+#: dashboards/project/instances/tables.py:293
+#: dashboards/project/volumes/tables.py:150
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:26
+msgid "Size"
+msgstr "Размер"
+
+#: dashboards/admin/instances/tables.py:79
+#: dashboards/admin/networks/tables.py:74
+#: dashboards/admin/networks/ports/tables.py:77
+#: dashboards/project/images_and_snapshots/images/tables.py:119
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:13
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:18
+#: dashboards/project/instances/tables.py:298
+#: dashboards/project/instances/templates/instances/_detail_overview.html:13
+#: dashboards/project/networks/tables.py:100
+#: dashboards/project/networks/ports/tables.py:44
+#: dashboards/project/networks/templates/networks/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:30
+#: dashboards/project/volumes/tables.py:154
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:17
+msgid "Status"
+msgstr "Статус"
+
+#: dashboards/admin/instances/tables.py:83
+#: dashboards/project/instances/tables.py:302
+msgid "Task"
+msgstr "Задача"
+
+#: dashboards/admin/instances/tables.py:90
+#: dashboards/project/instances/tables.py:309
+msgid "Power State"
+msgstr "Състояние"
+
+#: dashboards/admin/instances/views.py:49
+#: dashboards/project/access_and_security/views.py:76
+#: dashboards/project/access_and_security/floating_ips/workflows.py:65
+msgid "Unable to retrieve instance list."
+msgstr "Списъкът с инстанции не може да бъде получен."
+
+#: dashboards/admin/instances/views.py:63
+#: dashboards/admin/networks/views.py:48
+msgid "Unable to retrieve instance tenant information."
+msgstr ""
+
+#: dashboards/admin/instances/views.py:80
+#: dashboards/project/instances/views.py:82
+msgid "Unable to retrieve instance size information."
+msgstr ""
+
+#: dashboards/admin/instances/templates/instances/index.html:6
+msgid "All Instances"
+msgstr "Всички инстанции"
+
+#: dashboards/admin/networks/forms.py:36
+#: dashboards/admin/networks/tables.py:67
+#: dashboards/admin/projects/tables.py:65 dashboards/project/dashboard.py:40
+#: dashboards/project/instances/workflows.py:38
+msgid "Project"
+msgstr "Проект"
+
+#: dashboards/admin/networks/forms.py:37 dashboards/admin/networks/forms.py:74
+#: dashboards/admin/networks/tables.py:72
+#: dashboards/project/networks/tables.py:98
+#: dashboards/project/networks/templates/networks/_detail_overview.html:17
+msgid "Shared"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:46 dashboards/admin/users/forms.py:42
+msgid "Select a project"
+msgstr "Изберете проект"
+
+#: dashboards/admin/networks/forms.py:58
+#, python-format
+msgid "Network %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:64
+#, python-format
+msgid "Failed to create network %s"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:71
+#: dashboards/admin/networks/templates/networks/ports/_update.html:12
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:12
+#: dashboards/admin/users/forms.py:114
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:11
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:12
+#: dashboards/project/instances/templates/instances/_detail_overview.html:11
+#: dashboards/project/networks/forms.py:39
+#: dashboards/project/networks/templates/networks/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_update.html:12
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:11
+msgid "ID"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:82
+#: dashboards/project/networks/forms.py:48
+#, python-format
+msgid "Network %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:87
+#: dashboards/project/networks/forms.py:53
+#, python-format
+msgid "Failed to update network %s"
+msgstr ""
+
+#: dashboards/admin/networks/panel.py:25
+#: dashboards/admin/networks/tables.py:35
+#: dashboards/admin/networks/tables.py:80
+#: dashboards/admin/networks/templates/networks/index.html:3
+#: dashboards/admin/networks/templates/networks/index.html:6
+#: dashboards/project/instances/workflows.py:412
+#: dashboards/project/networks/panel.py:25
+#: dashboards/project/networks/tables.py:44
+#: dashboards/project/networks/tables.py:106
+#: dashboards/project/networks/templates/networks/index.html:3
+#: dashboards/project/networks/templates/networks/index.html:6
+msgid "Networks"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:34
+#: dashboards/project/networks/tables.py:43
+#: dashboards/project/networks/templates/networks/subnets/index.html:3
+#: dashboards/project/networks/templates/networks/subnets/index.html:6
+msgid "Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:41
+#: dashboards/project/networks/tables.py:59
+#, python-format
+msgid "Failed to delete network %s"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:49
+#: dashboards/admin/networks/templates/networks/_create.html:8
+#: dashboards/admin/networks/templates/networks/_create.html:23
+#: dashboards/admin/networks/templates/networks/create.html:3
+#: dashboards/admin/networks/templates/networks/create.html:6
+#: dashboards/project/networks/tables.py:67
+#: dashboards/project/networks/workflows.py:111
+#: dashboards/project/networks/templates/networks/_create.html:7
+#: dashboards/project/networks/templates/networks/_create.html:22
+#: dashboards/project/networks/templates/networks/create.html:3
+#: dashboards/project/networks/templates/networks/create.html:6
+msgid "Create Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:56
+#: dashboards/admin/networks/templates/networks/_update.html:7
+#: dashboards/project/networks/tables.py:74
+#: dashboards/project/networks/templates/networks/_update.html:7
+msgid "Edit Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:68
+#: dashboards/admin/networks/ports/forms.py:33
+#: dashboards/project/networks/subnets/forms.py:35
+msgid "Network Name"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:71
+#: dashboards/project/networks/tables.py:97
+msgid "Subnets Associated"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:76
+#: dashboards/admin/networks/ports/tables.py:79
+#: dashboards/project/networks/tables.py:102
+#: dashboards/project/networks/ports/tables.py:46
+#: dashboards/project/networks/templates/networks/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:32
+msgid "Admin State"
+msgstr ""
+
+#: dashboards/admin/networks/views.py:60
+#: dashboards/project/networks/views.py:52
+msgid "Network list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:91
+#: dashboards/project/networks/views.py:109
+msgid "Subnet list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:103
+#: dashboards/project/networks/views.py:121
+msgid "Port list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:118
+#: dashboards/project/networks/views.py:134
+#: dashboards/project/networks/subnets/tables.py:96
+#, python-format
+msgid "Unable to retrieve details for network \"%s\"."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:36
+#: dashboards/project/networks/subnets/forms.py:39
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:13
+msgid "Network ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:42
+#: dashboards/admin/networks/ports/forms.py:74
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:34
+msgid "Device ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:54
+#, python-format
+msgid "Port %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:59
+#, python-format
+msgid "Failed to create a port for network %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:84
+#, python-format
+msgid "Port %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:89
+#, python-format
+msgid "Failed to update port %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:34
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:6
+msgid "Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:35
+#: dashboards/admin/networks/ports/tables.py:83
+#: dashboards/project/networks/ports/tables.py:53
+msgid "Ports"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:41
+#: dashboards/admin/networks/subnets/tables.py:39
+#: dashboards/project/networks/subnets/tables.py:51
+#, python-format
+msgid "Failed to delete subnet %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:51
+#: dashboards/admin/networks/templates/networks/ports/_create.html:8
+#: dashboards/admin/networks/templates/networks/ports/_create.html:23
+#: dashboards/admin/networks/templates/networks/ports/create.html:3
+#: dashboards/admin/networks/templates/networks/ports/create.html:6
+msgid "Create Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:62
+#: dashboards/admin/networks/templates/networks/ports/_update.html:7
+msgid "Edit Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:75
+#: dashboards/project/networks/ports/tables.py:42
+msgid "Fixed IPs"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:76
+#: dashboards/project/networks/ports/tables.py:43
+msgid "Device Attached"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tabs.py:32
+#: dashboards/admin/overview/panel.py:29
+#: dashboards/admin/overview/templates/overview/usage.html:6
+#: dashboards/project/images_and_snapshots/images/tabs.py:27
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:27
+#: dashboards/project/instances/tabs.py:26
+#: dashboards/project/networks/ports/tabs.py:32
+#: dashboards/project/networks/subnets/tabs.py:32
+#: dashboards/project/overview/panel.py:29
+#: dashboards/project/overview/templates/overview/usage.html:6
+#: dashboards/project/volumes/tabs.py:27
+msgid "Overview"
+msgstr "Преглед"
+
+#: dashboards/admin/networks/ports/tabs.py:42
+#: dashboards/project/networks/ports/tabs.py:42
+msgid "Unable to retrieve port details."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:49
+#: dashboards/admin/networks/subnets/views.py:49
+#: dashboards/project/networks/subnets/views.py:54
+msgid "Unable to retrieve network."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:82
+msgid "Unable to retrieve port details"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/forms.py:43
+#, python-format
+msgid "Failed to retrieve network %s for a subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:32
+#: dashboards/project/networks/subnets/tables.py:44
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:6
+msgid "Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:33
+#: dashboards/admin/networks/subnets/tables.py:81
+#: dashboards/project/networks/subnets/tables.py:45
+#: dashboards/project/networks/subnets/tables.py:104
+msgid "Subnets"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:49
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:8
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:23
+#: dashboards/admin/networks/templates/networks/subnets/create.html:3
+#: dashboards/admin/networks/templates/networks/subnets/create.html:6
+#: dashboards/project/networks/workflows.py:53
+#: dashboards/project/networks/subnets/tables.py:61
+#: dashboards/project/networks/templates/networks/subnets/_create.html:8
+#: dashboards/project/networks/templates/networks/subnets/_create.html:23
+#: dashboards/project/networks/templates/networks/subnets/create.html:3
+#: dashboards/project/networks/templates/networks/subnets/create.html:6
+msgid "Create Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:60
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:7
+#: dashboards/project/networks/subnets/tables.py:72
+#: dashboards/project/networks/templates/networks/subnets/_update.html:7
+msgid "Edit Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:72
+#: dashboards/project/access_and_security/security_groups/forms.py:91
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:15
+msgid "CIDR"
+msgstr "CIDR"
+
+#: dashboards/admin/networks/subnets/tables.py:73
+#: dashboards/project/networks/workflows.py:66
+#: dashboards/project/networks/subnets/forms.py:53
+#: dashboards/project/networks/subnets/tables.py:85
+msgid "IP Version"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:74
+#: dashboards/project/networks/subnets/forms.py:54
+#: dashboards/project/networks/subnets/forms.py:104
+#: dashboards/project/networks/subnets/tables.py:86
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:19
+msgid "Gateway IP"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/views.py:82
+#: dashboards/project/networks/subnets/views.py:86
+msgid "Unable to retrieve subnet details"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_create.html:18
+#: dashboards/project/networks/templates/networks/_create.html:17
+msgid "Select a name for your network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:16
+#: dashboards/admin/networks/templates/networks/ports/_update.html:21
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:25
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:17
+#: dashboards/project/instances/templates/instances/_update.html:16
+#: dashboards/project/networks/templates/networks/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_update.html:25
+#: dashboards/settings/ec2/templates/ec2/download_form.html:17
+#: dashboards/settings/project/templates/project/_openrc.html:24
+#: dashboards/settings/user/templates/user/_settings.html:17
+msgid "Description:"
+msgstr "Описание:"
+
+#: dashboards/admin/networks/templates/networks/_update.html:17
+#: dashboards/project/networks/templates/networks/_update.html:17
+msgid "You may update the editable properties of your network here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:22
+#: dashboards/admin/networks/templates/networks/ports/_update.html:27
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:31
+#: dashboards/project/instances/templates/instances/_update.html:22
+#: dashboards/project/networks/templates/networks/_update.html:22
+#: dashboards/project/networks/templates/networks/subnets/_update.html:31
+msgid "Save Changes"
+msgstr "Запазване на промените"
+
+#: dashboards/admin/networks/templates/networks/update.html:3
+#: dashboards/admin/networks/templates/networks/update.html:6
+#: dashboards/project/networks/templates/networks/update.html:3
+#: dashboards/project/networks/templates/networks/update.html:6
+msgid "Update Network"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_create.html:18
+msgid ""
+"You can create a port for the network. If you specify device ID to be "
+"attached, the device specified will be attached to the port created."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_update.html:22
+msgid "You may update the editable properties of your port here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/update.html:3
+#: dashboards/admin/networks/templates/networks/ports/update.html:6
+msgid "Update Port"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:18
+#: dashboards/project/networks/templates/networks/subnets/_create.html:18
+msgid ""
+"You can create a subnet for the network. Any network address can be "
+"specified unless the network address does not overlap other subnets in the "
+"network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:14
+#: dashboards/project/networks/workflows.py:58
+#: dashboards/project/networks/subnets/forms.py:45
+#: dashboards/project/networks/subnets/tables.py:84
+#: dashboards/project/networks/templates/networks/subnets/_update.html:14
+msgid "Network Address"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:17
+#: dashboards/project/networks/templates/networks/subnets/_update.html:16
+msgid "IP version"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:26
+#: dashboards/project/networks/templates/networks/subnets/_update.html:26
+msgid "You may update the editable properties of your subnet here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/index.html:3
+#: dashboards/admin/networks/templates/networks/subnets/index.html:6
+#: dashboards/project/networks/templates/networks/detail.html:3
+msgid "Network Detail"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/update.html:3
+#: dashboards/admin/networks/templates/networks/subnets/update.html:6
+#: dashboards/project/networks/templates/networks/subnets/update.html:3
+#: dashboards/project/networks/templates/networks/subnets/update.html:6
+msgid "Update Subnet"
+msgstr ""
+
+#: dashboards/admin/overview/templates/overview/usage.html:3
+msgid "Usage Overview"
+msgstr "Преглед на потреблението"
+
+#: dashboards/admin/overview/templates/overview/usage.html:12
+msgid "Monitoring"
+msgstr "Мониторинг"
+
+#: dashboards/admin/projects/panel.py:29
+#: dashboards/admin/projects/tables.py:66
+#: dashboards/admin/projects/tables.py:95
+#: dashboards/admin/projects/templates/projects/index.html:8
+#: templates/403.html:24 templates/404.html:23 templates/500.html:23
+msgid "Projects"
+msgstr "Проекти"
+
+#: dashboards/admin/projects/tables.py:19
+msgid "Modify Users"
+msgstr "Промяна на потребителите"
+
+#: dashboards/admin/projects/tables.py:32
+msgid "View Usage"
+msgstr "Виж потреблението"
+
+#: dashboards/admin/projects/tables.py:39
+#: dashboards/admin/projects/templates/projects/_create.html:8
+#: dashboards/admin/projects/templates/projects/_create.html:23
+#: dashboards/admin/projects/templates/projects/create.html:6
+msgid "Create Project"
+msgstr "Създаване на проект"
+
+#: dashboards/admin/projects/tables.py:46
+#: dashboards/admin/projects/workflows.py:269
+#: dashboards/admin/projects/templates/projects/update.html:3
+#: dashboards/admin/projects/templates/projects/update.html:6
+msgid "Edit Project"
+msgstr "Редактиране на проект"
+
+#: dashboards/admin/projects/tables.py:90
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:60
+#: dashboards/project/networks/templates/networks/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:15
+msgid "Project ID"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:91
+#: dashboards/admin/projects/workflows.py:76
+#: dashboards/admin/projects/workflows.py:251
+#: dashboards/admin/services/tables.py:42 dashboards/admin/users/tables.py:40
+#: dashboards/admin/users/tables.py:115
+msgid "Enabled"
+msgstr "Включен"
+
+#: dashboards/admin/projects/tables.py:104
+msgid "Remove"
+msgstr "Премахни"
+
+#: dashboards/admin/projects/tables.py:105
+msgid "Removed"
+msgstr "Премахнат"
+
+#: dashboards/admin/projects/tables.py:106 dashboards/admin/users/tables.py:41
+#: dashboards/admin/users/tables.py:75
+#: dashboards/project/instances/workflows.py:39
+msgid "User"
+msgstr "Потребител"
+
+#: dashboards/admin/projects/tables.py:107 dashboards/admin/users/panel.py:29
+#: dashboards/admin/users/tables.py:42 dashboards/admin/users/tables.py:76
+#: dashboards/admin/users/tables.py:122
+#: dashboards/admin/users/templates/users/index.html:8
+msgid "Users"
+msgstr "Потревители"
+
+#: dashboards/admin/projects/tables.py:125
+msgid "Unable to retrieve role information."
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:130
+msgid "Roles"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:134
+msgid "Users For Project"
+msgstr "Потребители за проект"
+
+#: dashboards/admin/projects/tables.py:142
+msgid "Add To Project"
+msgstr "Добави към проект"
+
+#: dashboards/admin/projects/tables.py:154
+msgid "Add New Users"
+msgstr "Добавяне на нови потребители"
+
+#: dashboards/admin/projects/views.py:67
+msgid "Unable to retrieve project information."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:87
+msgid "Unable to retrieve project list."
+msgstr "Списъкът с проектите не може да бъде получен."
+
+#: dashboards/admin/projects/views.py:110
+msgid "Unable to retrieve users."
+msgstr "Потребителите не могат да бъдат получени."
+
+#: dashboards/admin/projects/views.py:154
+msgid "Unable to retrieve default quota values."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:182
+msgid "Unable to retrieve project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:37
+msgid "Injected File Content Bytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:38
+msgid "Metadata Items"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:41
+msgid "Injected Files"
+msgstr "Инжектирани файлове"
+
+#: dashboards/admin/projects/workflows.py:44
+#: dashboards/admin/volumes/panel.py:9 dashboards/admin/volumes/tables.py:15
+#: dashboards/admin/volumes/templates/volumes/index.html:3
+#: dashboards/admin/volumes/templates/volumes/index.html:6
+#: dashboards/project/volumes/panel.py:25
+#: dashboards/project/volumes/tables.py:38
+#: dashboards/project/volumes/tables.py:171
+#: dashboards/project/volumes/tables.py:183
+#: dashboards/project/volumes/templates/volumes/index.html:3
+#: dashboards/project/volumes/templates/volumes/index.html:6
+msgid "Volumes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:45
+msgid "Gigabytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:46
+msgid "RAM (MB)"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:47
+#: dashboards/project/access_and_security/floating_ips/tables.py:50
+#: dashboards/project/access_and_security/floating_ips/tables.py:128
+msgid "Floating IPs"
+msgstr "Плаващи IP адреси"
+
+#: dashboards/admin/projects/workflows.py:50
+msgid "Quota"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:52
+msgid "From here you can set quotas (max limits) for the project."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:81
+#: dashboards/admin/projects/workflows.py:254
+msgid "Project Info"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:82
+#: dashboards/admin/projects/templates/projects/_create.html:18
+msgid "From here you can create a new project to organize users."
+msgstr ""
+"От тук можете да създадете нов проект за да организирате потребителите."
+
+#: dashboards/admin/projects/workflows.py:101
+msgid "Unable to retrieve user list. Please try again later."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:155
+#: dashboards/admin/projects/templates/projects/_update_members.html:16
+msgid "Project Members"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:169
+#: dashboards/admin/users/views.py:47
+msgid "Unable to retrieve user list."
+msgstr "Списъкът с потребители не може да бъде получен."
+
+#: dashboards/admin/projects/workflows.py:180
+msgid "Add Project"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:181
+msgid "Finish"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:182
+#, python-format
+msgid "Created new project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:183
+#, python-format
+msgid "Unable to create project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:227
+#, python-format
+msgid "Failed to add %s project members and set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:246
+msgid "Unable to set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:256
+msgid "From here you can edit the project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:271
+#, python-format
+msgid "Modified project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:272
+#, python-format
+msgid "Unable to modify project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:342
+#, python-format
+msgid "Failed to modify %s project members and update project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:363
+msgid ""
+"Modified project information and members, but unable to modify project "
+"quotas."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:8
+#: dashboards/admin/projects/templates/projects/add_user.html:3
+#: dashboards/admin/projects/templates/projects/add_user.html:6
+msgid "Add User To Project"
+msgstr "Добавяне на потребител към проект"
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:18
+msgid "Select the user role for the project."
+msgstr "Изберете ролята на потребителя за проекта."
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:23
+msgid "Add"
+msgstr "Добавяне"
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:7
+#, python-format
+msgid "Create User for project '%(tenant_name)s'."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:18
+msgid "From here you can create a new user to add to this project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:23
+#: dashboards/admin/users/tables.py:20
+#: dashboards/admin/users/templates/users/_create.html:7
+#: dashboards/admin/users/templates/users/_create.html:22
+#: dashboards/admin/users/templates/users/create.html:7
+msgid "Create User"
+msgstr "Създаване на потребител"
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:7
+#: dashboards/admin/projects/templates/projects/_quotas.html:22
+msgid "Update Quota"
+msgstr "Обновяване на квотата"
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:17
+#, python-format
+msgid ""
+"From here you can edit quotas (max limits) for the project %(tenant.name)s."
+msgstr ""
+"От тук можете да променяте квотите (максималните лимити) за проекта "
+"%(tenant.name)s."
+
+#: dashboards/admin/projects/templates/projects/_update.html:8
+#: dashboards/admin/projects/templates/projects/_update.html:23
+#: dashboards/admin/projects/templates/projects/quotas.html:6
+msgid "Update Project"
+msgstr "Обновяване на проекта"
+
+#: dashboards/admin/projects/templates/projects/_update.html:18
+msgid "From here you can edit a project."
+msgstr "От тук можете да промените проект."
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:7
+msgid ""
+"From here you can add and remove members to this project from the list of "
+"all available users."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:10
+msgid "All Users"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:25
+#: dashboards/admin/projects/templates/projects/_update_members.html:32
+msgid "No users found."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/create_user.html:3
+#: dashboards/admin/projects/templates/projects/create_user.html:6
+msgid "Add New User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:3
+msgid "Project Usage Overview"
+msgstr "Преглед на потреблението на проекта"
+
+#: dashboards/admin/projects/templates/projects/usage.html:7
+msgid "Project Usage"
+msgstr "Потребление на проекта"
+
+#: dashboards/admin/projects/templates/projects/users.html:7
+msgid "Users for Project"
+msgstr "Потребители на проекта"
+
+#: dashboards/admin/quotas/panel.py:29 dashboards/admin/quotas/tables.py:36
+msgid "Quotas"
+msgstr "Квоти"
+
+#: dashboards/admin/quotas/tables.py:28
+msgid "Quota Name"
+msgstr "Име на квотата"
+
+#: dashboards/admin/quotas/tables.py:29
+msgid "Limit"
+msgstr "Лимит"
+
+#: dashboards/admin/quotas/views.py:46
+msgid "Unable to get quota info."
+msgstr "Информацията за квотата не може да бъде получена."
+
+#: dashboards/admin/quotas/templates/quotas/index.html:8
+msgid "Default Quotas"
+msgstr "Квоти по подразбиране"
+
+#: dashboards/admin/services/panel.py:29
+#: dashboards/admin/services/tables.py:47
+#: dashboards/admin/services/templates/services/index.html:8
+msgid "Services"
+msgstr "Услуги"
+
+#: dashboards/admin/services/tables.py:37
+msgid "Id"
+msgstr ""
+
+#: dashboards/admin/services/tables.py:39
+msgid "Service"
+msgstr "Услуга"
+
+#: dashboards/admin/users/forms.py:54
+msgid "Passwords do not match."
+msgstr "Паролите не съвпадат."
+
+#: dashboards/admin/users/forms.py:62 dashboards/admin/users/forms.py:115
+#: dashboards/admin/users/tables.py:108
+msgid "User Name"
+msgstr "Потребителско име"
+
+#: dashboards/admin/users/forms.py:63 dashboards/admin/users/forms.py:116
+#: dashboards/admin/users/tables.py:109
+msgid "Email"
+msgstr "Имейл"
+
+#: dashboards/admin/users/forms.py:65 dashboards/admin/users/forms.py:117
+msgid "Password"
+msgstr "Парола"
+
+#: dashboards/admin/users/forms.py:70 dashboards/admin/users/forms.py:124
+msgid "Confirm Password"
+msgstr "Парола отново"
+
+#: dashboards/admin/users/forms.py:73 dashboards/admin/users/forms.py:127
+msgid "Primary Project"
+msgstr "Основен проект"
+
+#: dashboards/admin/users/forms.py:75
+msgid "Role"
+msgstr "Роля"
+
+#: dashboards/admin/users/forms.py:96
+#, python-format
+msgid "User \"%s\" was successfully created."
+msgstr "Потребителят \"%s\"беше успешно създаден."
+
+#: dashboards/admin/users/forms.py:106
+msgid "Unable to add userto primary project."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:110
+msgid "Unable to create user."
+msgstr "Потребителят не може да бъде създаден."
+
+#: dashboards/admin/users/forms.py:151
+msgid "name"
+msgstr "име"
+
+#: dashboards/admin/users/forms.py:151
+msgid "email"
+msgstr "имейл"
+
+#: dashboards/admin/users/forms.py:160
+msgid "primary project"
+msgstr "основен проект"
+
+#: dashboards/admin/users/forms.py:173
+#, python-format
+msgid "The user %s has no role defined for"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:181
+msgid "password"
+msgstr "парола"
+
+#: dashboards/admin/users/forms.py:190
+msgid "User has been updated successfully."
+msgstr "Потребителят беше обновен успешно."
+
+#: dashboards/admin/users/forms.py:194
+#, python-format
+msgid "Unable to update %(attributes)s for the user."
+msgstr ""
+
+#: dashboards/admin/users/tables.py:32
+#: dashboards/project/images_and_snapshots/images/tables.py:68
+msgid "Edit"
+msgstr "Промяна"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Enable"
+msgstr "Включи"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Disable"
+msgstr "Изключи"
+
+#: dashboards/admin/users/tables.py:40
+msgid "Disabled"
+msgstr "Изключен"
+
+#: dashboards/admin/users/tables.py:63
+msgid "You cannot disable the user you are currently logged in as."
+msgstr "Не можете да изключите потребителя с който сте влезли."
+
+#: dashboards/admin/users/tables.py:114
+msgid "User ID"
+msgstr ""
+
+#: dashboards/admin/users/views.py:70
+msgid "Unable to update user."
+msgstr "Потребителят не може да бъде обновен."
+
+#: dashboards/admin/users/views.py:104
+msgid "Unable to retrieve user roles."
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_create.html:17
+msgid "From here you can create a new user and assign them to a project."
+msgstr "От тук можете да създадете нов потребител и да го добавите към проект."
+
+#: dashboards/admin/users/templates/users/_update.html:7
+#: dashboards/admin/users/templates/users/_update.html:22
+#: dashboards/admin/users/templates/users/update.html:7
+msgid "Update User"
+msgstr "Обновяване на потребител"
+
+#: dashboards/admin/users/templates/users/_update.html:17
+msgid ""
+"From here you can edit the user's details, including their default project."
+msgstr ""
+"От тук можете да променяте детайлите на потребителите, включително техният "
+"основен проект."
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:3
+#: dashboards/project/volumes/templates/volumes/detail.html:3
+msgid "Volume Details"
+msgstr ""
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:6
+#: dashboards/project/volumes/templates/volumes/detail.html:6
+msgid "Volume Detail"
+msgstr ""
+
+#: dashboards/project/dashboard.py:24
+msgid "Manage Compute"
+msgstr ""
+
+#: dashboards/project/dashboard.py:35
+msgid "Object Store"
+msgstr ""
+
+#: dashboards/project/access_and_security/panel.py:26
+#: dashboards/project/instances/workflows.py:348
+msgid "Access & Security"
+msgstr "Достъп и сигурност"
+
+#: dashboards/project/access_and_security/views.py:51
+msgid "Unable to retrieve keypair list."
+msgstr "Списъкът с ключови двойки не може да бъде получен."
+
+#: dashboards/project/access_and_security/views.py:60
+#: dashboards/project/access_and_security/security_groups/views.py:74
+msgid "Unable to retrieve security groups."
+msgstr "Групите за сигурност не могат да бъдат получени."
+
+#: dashboards/project/access_and_security/views.py:69
+#: dashboards/project/access_and_security/floating_ips/workflows.py:49
+msgid "Unable to retrieve floating IP addresses."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:32
+msgid "Pool"
+msgstr "Басейн"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:43
+#, python-format
+msgid "Allocated Floating IP %(ip)s."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:47
+msgid "Unable to allocate Floating IP."
+msgstr "Не може да се алокира плаващ IP адрес."
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:37
+msgid "Allocate IP To Project"
+msgstr "Алокация на IP за проект"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:47
+msgid "Release"
+msgstr "Освободи"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:48
+msgid "Released"
+msgstr "Освободен"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:49
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:22
+msgid "Floating IP"
+msgstr "Плаващ IP адрес"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:6
+#: dashboards/project/instances/tables.py:219
+msgid "Associate Floating IP"
+msgstr "Асоциация на плаващ IP адрес"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:76
+msgid "Disassociate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:90
+#, python-format
+msgid "Successfully disassociated Floating IP: %s"
+msgstr "Успешна дисоциация на плаващо IP: %s"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:94
+msgid "Unable to disassociate floating IP."
+msgstr "Не може да се дисоциира плаващия IP адрес."
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:114
+#: dashboards/project/access_and_security/floating_ips/workflows.py:36
+#: dashboards/project/instances/tables.py:69
+#: dashboards/project/instances/tables.py:89
+#: dashboards/project/instances/tables.py:106
+#: dashboards/project/instances/tables.py:135
+#: dashboards/project/volumes/tables.py:206
+msgid "Instance"
+msgstr "Инстанция"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:117
+msgid "Floating IP Pool"
+msgstr "Басейн с плаващи IP адреси"
+
+#: dashboards/project/access_and_security/floating_ips/views.py:65
+msgid "Unable to retrieve floating IP pools."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:68
+msgid "No floating IP pools available."
+msgstr "Не са налични басейни с плаващи IP адреси."
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:40
+msgid "Select the IP address you wish to associate with the selected instance."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:53
+msgid "Select an IP address"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:55
+msgid "No IP addresses available"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:76
+#: dashboards/project/volumes/forms.py:160
+msgid "Select an instance"
+msgstr "Изберете инстанция"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:78
+#: dashboards/project/volumes/forms.py:162
+msgid "No instances available"
+msgstr "Няма налични инстанции"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:97
+msgid "Manage Floating IP Associations"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:98
+msgid "Associate"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:99
+#, python-format
+msgid "IP address %s associated."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:100
+#, python-format
+msgid "Unable to associate IP address %s."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:38
+#: dashboards/project/access_and_security/keypairs/forms.py:49
+#: dashboards/project/access_and_security/keypairs/tables.py:52
+msgid "Keypair Name"
+msgstr "Име на ключова двойка"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:40
+msgid ""
+"Keypair names may only contain letters, numbers, underscores and hyphens."
+msgstr ""
+"Имената на ключовите двойки могат да съдържат само букви, числа, долни черти "
+"и тирета."
+
+#: dashboards/project/access_and_security/keypairs/forms.py:51
+msgid "Public Key"
+msgstr "Публичен ключ"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:60
+#, python-format
+msgid "Successfully imported public key: %s"
+msgstr "Успешно зареждане на публичен ключ: %s"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:65
+msgid "Unable to import keypair."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:30
+#: dashboards/project/instances/tables.py:295
+#: dashboards/project/instances/workflows.py:335
+msgid "Keypair"
+msgstr "Ключова двойка"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:31
+#: dashboards/project/access_and_security/keypairs/tables.py:60
+msgid "Keypairs"
+msgstr "Ключови двойки"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:39
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html:6
+msgid "Import Keypair"
+msgstr "Зареждане на ключова двойка"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:46
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html:6
+msgid "Create Keypair"
+msgstr "Създаване на ключова двойка"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:53
+msgid "Fingerprint"
+msgstr "Фингърпринт"
+
+#: dashboards/project/access_and_security/keypairs/views.py:74
+#, python-format
+msgid "Unable to create keypair: %(exc)s"
+msgstr "Не може да се създаде ключовата двойка: %(exc)s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:46
+#, python-format
+msgid "Successfully created security group: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:52
+msgid "Unable to create security group."
+msgstr "Групата за сигурност не може да бъде създадена."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:57
+#: dashboards/project/access_and_security/security_groups/tables.py:93
+msgid "IP Protocol"
+msgstr "IP протокол"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:61
+msgid "The protocol which this rule should be applied to."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:65
+#: dashboards/project/access_and_security/security_groups/forms.py:71
+#: dashboards/project/access_and_security/security_groups/tables.py:95
+msgid "From Port"
+msgstr "От порт"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:66
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP type in the range (-1: 255)"
+msgstr ""
+"TCP/UDP: Въведете число от 1 до 65535. ICMP: въведете стойност за ICMP в "
+"диапазона (-1: 255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:72
+#: dashboards/project/images_and_snapshots/images/tables.py:115
+msgid "Type"
+msgstr "Тип"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:74
+#: dashboards/project/access_and_security/security_groups/forms.py:80
+#: dashboards/project/access_and_security/security_groups/tables.py:96
+msgid "To Port"
+msgstr "До порт"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:75
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP code in the range (-1: 255)"
+msgstr ""
+"TCP/UDP: Въведете число от 1 до 65535. ICMP: въведете стойност за ICMP код в "
+"диапазона (-1: 255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:81
+msgid "Code"
+msgstr "Код"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:84
+msgid "Source Group"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:86
+msgid ""
+"To specify an allowed IP range, select CIDR. To allow access from all "
+"members of another security group select Source Group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:94
+msgid "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:121
+msgid "The ICMP type is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:124
+msgid "The ICMP code is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:127
+msgid "The ICMP type not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:130
+msgid "The ICMP code not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:134
+msgid "The \"from\" port number is invalid."
+msgstr "Числото за \"от\" порт е невалидно."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:137
+msgid "The \"to\" port number is invalid."
+msgstr "Числото за \"до\" порт е невалидно."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:140
+msgid ""
+"The \"to\" port number must be greater than or equal to the \"from\" port "
+"number."
+msgstr ""
+"Числото за \"до\" порт трябва да е по-голямо или равно на числото за \"от\" "
+"порт."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:146
+msgid "Either CIDR or Source Group may be specified, but not both."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:168
+#, python-format
+msgid "Successfully added rule: %s"
+msgstr "Успешно добавено правило: %s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:173
+msgid "Unable to add rule to security group."
+msgstr "Правилото не може да бъде добавено към групата за сигурност."
+
+#: dashboards/project/access_and_security/security_groups/tables.py:31
+msgid "Security Group"
+msgstr "Група за сигурност"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:32
+#: dashboards/project/access_and_security/security_groups/tables.py:66
+#: dashboards/project/instances/workflows.py:340
+#: dashboards/project/instances/templates/instances/_detail_overview.html:49
+msgid "Security Groups"
+msgstr "Групи за сигурност"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:45
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html:6
+msgid "Create Security Group"
+msgstr "Създаване на група за сигурност"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:52
+msgid "Edit Rules"
+msgstr "Промяна на правилата"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:72
+msgid "Rule"
+msgstr "Правило"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:73
+msgid "Rules"
+msgstr "Правила"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:97
+msgid "Source"
+msgstr "Източник"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:107
+msgid "Security Group Rules"
+msgstr "Правила на групата за сигурност"
+
+#: dashboards/project/access_and_security/security_groups/views.py:60
+msgid "Unable to retrieve security group."
+msgstr "Групата за сигурност не може да бъде получена."
+
+#: dashboards/project/access_and_security/security_groups/views.py:80
+#, python-format
+msgid "%s (current)"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/index.html:6
+msgid "Access &amp; Security"
+msgstr "Достъп &amp; сигурност"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:8
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html:3
+msgid "Allocate Floating IP"
+msgstr "Алокация на плаващ IP адрес"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:18
+msgid "Allocate a floating IP from a given floating ip pool."
+msgstr "Алокация на плаващ IP адрес от даден басейн с плаващи IP адреси."
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:20
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:19
+msgid "Project Quotas"
+msgstr "Квоти на проекта"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:31
+msgid "Allocate IP"
+msgstr "Алокация на IP адрес"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:17
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:17
+msgid ""
+"Keypairs are ssh credentials which are injected into images when they are "
+"launched. Creating a new key pair registers the public key and downloads the "
+"private key (a .pem file)."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:18
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:18
+msgid "Protect and use the key as you would any normal ssh private key."
+msgstr "Пазете и използвайте ключа като всеки нормален ssh частен ключ."
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:6
+msgid "Download Keypair"
+msgstr "Свали ключовата двойка"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:11
+#, python-format
+msgid ""
+"The keypair &quot;%(keypair_name)s&quot; should download automatically. If "
+"not use the link below."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:15
+#, python-format
+msgid "Download keypair &quot;%(keypair_name)s&quot;"
+msgstr "Свали ключовата двойка \"%(keypair_name)s\""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:18
+msgid "From here you can create a new security group"
+msgstr "От тук можете да създадете нова група за сигурност"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:9
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html:6
+msgid "Edit Security Group Rules"
+msgstr "Промяна на правилата на групата за сигурност"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:12
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:19
+msgid "Add Rule"
+msgstr "Добавяне на правило"
+
+#: dashboards/project/containers/browsers.py:26
+msgid "Swift"
+msgstr ""
+
+#: dashboards/project/containers/browsers.py:29
+#: dashboards/project/containers/tables.py:40
+msgid "Container"
+msgstr "Контейнер"
+
+#: dashboards/project/containers/forms.py:39
+msgid "Slash is not an allowed character."
+msgstr "Наклонената черта е невалиден символ."
+
+#: dashboards/project/containers/forms.py:49
+#: dashboards/project/containers/tables.py:121
+msgid "Container Name"
+msgstr "Име на контейнер"
+
+#: dashboards/project/containers/forms.py:57
+msgid "Container created successfully."
+msgstr "Контейнерът беше създаден успешно."
+
+#: dashboards/project/containers/forms.py:68
+msgid "Folder created successfully."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:71
+msgid "Unable to create container."
+msgstr "Контейнерът не може да бъде създаден."
+
+#: dashboards/project/containers/forms.py:79
+#: dashboards/project/containers/tables.py:253
+msgid "Object Name"
+msgstr "Име на обект"
+
+#: dashboards/project/containers/forms.py:81
+msgid "File"
+msgstr "Файл"
+
+#: dashboards/project/containers/forms.py:95
+msgid "Object was successfully uploaded."
+msgstr "Обектът беше качен успешно."
+
+#: dashboards/project/containers/forms.py:98
+msgid "Unable to upload object."
+msgstr "Обектът не може да бъде качен."
+
+#: dashboards/project/containers/forms.py:102
+msgid "Destination container"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:106
+msgid "Destination object name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:137
+#: dashboards/project/containers/forms.py:163
+msgid "Unable to copy object."
+msgstr "Обектът не беше копиран."
+
+#: dashboards/project/containers/forms.py:153
+#, python-format
+msgid "Copied \"%(orig)s\" to \"%(dest)s\" as \"%(new)s\"."
+msgstr ""
+
+#: dashboards/project/containers/panel.py:29
+#: dashboards/project/containers/tables.py:41
+#: dashboards/project/containers/tables.py:128
+#: dashboards/project/containers/templates/containers/index.html:7
+msgid "Containers"
+msgstr "Контейнери"
+
+#: dashboards/project/containers/tables.py:62
+#: dashboards/project/containers/templates/containers/_create.html:7
+#: dashboards/project/containers/templates/containers/_create.html:22
+#: dashboards/project/containers/templates/containers/create.html:6
+msgid "Create Container"
+msgstr "Създаване на контейнер"
+
+#: dashboards/project/containers/tables.py:69
+msgid "View Container"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:81
+#: dashboards/project/containers/templates/containers/_upload.html:23
+#: dashboards/project/containers/templates/containers/upload.html:3
+msgid "Upload Object"
+msgstr "Качване на обект"
+
+#: dashboards/project/containers/tables.py:137
+#: dashboards/project/containers/tables.py:156
+msgid "Object"
+msgstr "Обект"
+
+#: dashboards/project/containers/tables.py:138
+#: dashboards/project/containers/tables.py:157
+#: dashboards/project/containers/tables.py:263
+msgid "Objects"
+msgstr "Обекти"
+
+#: dashboards/project/containers/tables.py:149
+msgid "Folder"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:150
+msgid "Folders"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:163
+msgid "Copy"
+msgstr "Копиране"
+
+#: dashboards/project/containers/tables.py:176
+msgid "Download"
+msgstr "Сваляне"
+
+#: dashboards/project/containers/tables.py:232
+msgid "Create Folder"
+msgstr ""
+
+#: dashboards/project/containers/views.py:53
+msgid "Unable to retrieve container list."
+msgstr "Списъкът с контейнери не може да бъде получен."
+
+#: dashboards/project/containers/views.py:82
+msgid "Unable to retrieve object list."
+msgstr "Списъкът с обекти не може да бъде получен."
+
+#: dashboards/project/containers/views.py:166
+msgid "Unable to retrieve object."
+msgstr "Обектът не може да бъде получен."
+
+#: dashboards/project/containers/views.py:200
+msgid "Unable to list containers."
+msgstr "Списъкът с контейнери не може да бъде показан."
+
+#: dashboards/project/containers/templates/containers/_copy.html:7
+#: dashboards/project/containers/templates/containers/_copy.html:22
+#: dashboards/project/containers/templates/containers/copy.html:3
+#: dashboards/project/containers/templates/containers/copy.html:6
+msgid "Copy Object"
+msgstr "Копиране на обект"
+
+#: dashboards/project/containers/templates/containers/_copy.html:17
+msgid ""
+"Make a new copy of an existing object to store in this or another container. "
+"You may also specify a path at which the new copy should live inside of the "
+"selected container."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_create.html:17
+msgid ""
+"A container is a storage compartment for your data and provides a way for "
+"you to organize your data. You can think of a container as a folder in "
+"Windows &reg; or a directory in UNIX &reg;. The primary difference between a "
+"container and these other file system concepts is that containers cannot be "
+"nested. You can, however, create an unlimited number of containers within "
+"your account. Data must be stored in a container so you must have at least "
+"one container defined in your account prior to uploading data."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:8
+msgid "Upload Object To Container"
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:18
+msgid ""
+"An object is the basic storage entity and any optional metadata that "
+"represents the files you store in the OpenStack Object Storage system. When "
+"you upload data to OpenStack Object Storage, the data is stored as-is (no "
+"compression or encryption) and consists of a location (container), the "
+"object's name, and any metadata consisting of key/value pairs."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/upload.html:6
+msgid "Upload Objects"
+msgstr "Качване на обект"
+
+#: dashboards/project/images_and_snapshots/panel.py:26
+msgid "Images & Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:63
+msgid "Unable to retrieve images."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:74
+msgid "Unable to retrieve snapshots."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:82
+#: dashboards/project/volumes/forms.py:65
+msgid "Unable to retrieve volume snapshots."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:42
+msgid "Image Location"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:43
+msgid "An external (HTTP) URL to load the image from."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:46
+#: dashboards/project/images_and_snapshots/images/forms.py:130
+#: dashboards/project/images_and_snapshots/images/tables.py:126
+msgid "Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:50
+msgid "AKI - Amazon Kernel Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:53
+msgid "AMI - Amazon Machine Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:56
+msgid "ARI - Amazon Ramdisk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:59
+msgid "ISO - Optical Disk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:61
+msgid "QCOW2 - QEMU Emulator"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:68
+msgid "Minimum Disk (GB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:69
+#: dashboards/project/images_and_snapshots/images/forms.py:76
+msgid ""
+"The minimum disk size required to boot the image. If unspecified, this value "
+"defaults to 0 (no minimum)."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:75
+msgid "Minimum Ram (MB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:82
+#: dashboards/project/images_and_snapshots/images/forms.py:134
+#: dashboards/project/images_and_snapshots/images/tables.py:123
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:15
+msgid "Public"
+msgstr "Публичен"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:106
+#, python-format
+msgid "Your image %s has been queued for creation."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:110
+msgid "Unable to create new image."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:116
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:48
+msgid "Kernel ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:121
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:52
+msgid "Ramdisk ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:126
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:44
+msgid "Architecture"
+msgstr "Архитектура"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:138
+#, python-format
+msgid "Unable to update image \"%s\"."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:162
+msgid "Image was successfully updated."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tables.py:34
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:33
+#: dashboards/project/instances/workflows.py:455
+msgid "Launch"
+msgstr "Стартиране"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:46
+#: dashboards/project/images_and_snapshots/images/tables.py:82
+#: dashboards/project/instances/workflows.py:168
+#: dashboards/project/instances/workflows.py:173
+msgid "Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tables.py:61
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:31
+msgid "Create Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tabs.py:38
+msgid "Unable to retrieve image details."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/views.py:61
+msgid "Unable to retrieve image."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:37
+msgid "Instance ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:40
+#: dashboards/project/volumes/forms.py:193
+msgid "Snapshot Name"
+msgstr "Име на запазеното състояние"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:50
+#, python-format
+msgid "Snapshot \"%(name)s\" created for instance \"%(inst)s\""
+msgstr ""
+"Запазено състояние \"%(name)s\" беше създадено за инстанция \"%(inst)s\""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:56
+msgid "Unable to create snapshot."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:48
+#: dashboards/project/instances/workflows.py:107
+#: dashboards/project/instances/workflows.py:169
+msgid "Snapshot"
+msgstr "Запазване на състоянието"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:49
+msgid "Snapshots"
+msgstr "Запазени състояния"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:55
+msgid "Instance Snapshots"
+msgstr "Запазени състояния на инстанцията"
+
+#: dashboards/project/images_and_snapshots/snapshots/views.py:53
+msgid "Unable to retrieve instance."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:6
+msgid "Images &amp; Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:6
+msgid "Create An Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:18
+msgid "Specify an image to upload to the Image Service."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:21
+msgid ""
+"Currently only images available via an HTTP URL are supported. The image "
+"location must be accessible to the Image Service. Compressed image binaries "
+"are supported (.zip and .tar.gz.)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:24
+msgid "Please note: "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:25
+msgid ""
+"The Image Location field MUST be a valid and direct URL to the image binary. "
+"URLs that redirect or serve error pages will result in unusable images."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:3
+msgid "Image Overview"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:6
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:7
+#: dashboards/project/instances/templates/instances/_detail_overview.html:6
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:6
+msgid "Info"
+msgstr "Информация"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:17
+msgid "Checksum"
+msgstr "Контролна сума"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:19
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:39
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:28
+msgid "Created"
+msgstr "Създаден на"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:21
+msgid "Updated"
+msgstr "Оновен на"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:27
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:34
+#: dashboards/project/instances/templates/instances/_detail_overview.html:19
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:23
+msgid "Specs"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:32
+msgid "Container Format"
+msgstr "Формат на контейнера"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:34
+msgid "Disk Format"
+msgstr "Формат на диска"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:40
+msgid "Custom Properties"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:56
+msgid "Euca2ools state"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:64
+msgid "Image Type"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html:4
+msgid "Image Detail "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:8
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:3
+#: dashboards/project/instances/tables.py:179
+#: dashboards/project/volumes/tables.py:76
+msgid "Create Snapshot"
+msgstr "Създаване на запазено състояние"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:18
+msgid "Snapshots preserve the disk state of a running instance."
+msgstr ""
+"Запазеното състояние запазва състоянието на диска на работеща инстанция."
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:20
+#: dashboards/project/instances/workflows.py:75
+#: dashboards/project/instances/workflows.py:110
+#: dashboards/project/instances/templates/instances/_detail_overview.html:93
+#: dashboards/project/volumes/tables.py:37
+#: dashboards/project/volumes/tables.py:182
+msgid "Volume"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:38
+#: dashboards/project/instances/templates/instances/_detail_overview.html:29
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:27
+msgid "GB"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:6
+msgid "Create a Snapshot"
+msgstr "Създаване на запазено състояние"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:3
+msgid "Volume Snapshot Details"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:6
+msgid "Volume Snapshot Detail"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:34
+#: dashboards/project/instances/workflows.py:76
+msgid "Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:35
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:85
+msgid "Volume Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:43
+#: dashboards/project/volumes/tables.py:59
+#: dashboards/project/volumes/templates/volumes/_create.html:8
+#: dashboards/project/volumes/templates/volumes/_create.html:55
+msgid "Create Volume"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:80
+#: dashboards/project/volumes/forms.py:26
+msgid "Volume Name"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:41
+#, fuzzy
+msgid "Unable to retrieve snapshot details."
+msgstr "Детайлите за инстанцията не могат да бъдат получени."
+
+#: dashboards/project/instances/forms.py:45
+#, python-format
+msgid "Instance \"%s\" updated."
+msgstr "Инстанцията \"%s\" беше обновена."
+
+#: dashboards/project/instances/forms.py:50
+msgid "Unable to update instance."
+msgstr "Инстанцията не може да бъде обновена."
+
+#: dashboards/project/instances/tables.py:67
+msgid "Terminate"
+msgstr "Прекратяване"
+
+#: dashboards/project/instances/tables.py:68
+msgid "Scheduled termination of"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:87
+msgid "Reboot"
+msgstr "Рестартиране"
+
+#: dashboards/project/instances/tables.py:88
+msgid "Rebooted"
+msgstr "Рестартирана"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Pause"
+msgstr "Пауза"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Unpause"
+msgstr "Без пауза"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Paused"
+msgstr "На пауза"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Unpaused"
+msgstr "Не е на пауза"
+
+#: dashboards/project/instances/tables.py:133
+msgid "Suspend"
+msgstr "Заспиване"
+
+#: dashboards/project/instances/tables.py:133
+msgid "Resume"
+msgstr "Продължи"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Suspended"
+msgstr "Заспала"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Resumed"
+msgstr "Продължена"
+
+#: dashboards/project/instances/tables.py:162
+#: dashboards/project/instances/workflows.py:454
+#: dashboards/project/instances/templates/instances/launch.html:3
+#: dashboards/project/instances/templates/instances/launch.html:6
+msgid "Launch Instance"
+msgstr "Стартиране на инстанция"
+
+#: dashboards/project/instances/tables.py:169
+#: dashboards/project/instances/templates/instances/_update.html:7
+msgid "Edit Instance"
+msgstr "Промяна на инстанция"
+
+#: dashboards/project/instances/tables.py:189
+msgid "VNC Console"
+msgstr "VNC Console"
+
+#: dashboards/project/instances/tables.py:204
+msgid "View Log"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:252
+#, python-format
+msgid "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disk"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:259
+#: dashboards/project/instances/tables.py:266
+msgid "Not available"
+msgstr "Не е налично"
+
+#: dashboards/project/instances/tabs.py:36
+msgid "Log"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:48
+#: dashboards/project/instances/views.py:106
+#, python-format
+msgid "Unable to get log for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:55
+msgid "VNC"
+msgstr "VNC"
+
+#: dashboards/project/instances/tabs.py:70
+#: dashboards/project/instances/views.py:122
+#, python-format
+msgid "Unable to get VNC console for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/views.py:59
+msgid "Unable to retrieve instances."
+msgstr ""
+
+#: dashboards/project/instances/views.py:144
+msgid "Unable to retrieve instance details."
+msgstr "Детайлите за инстанцията не могат да бъдат получени."
+
+#: dashboards/project/instances/views.py:179
+#, python-format
+msgid "Unable to retrieve details for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:53
+msgid "Project & User"
+msgstr "Проект и потребител"
+
+#: dashboards/project/instances/workflows.py:66
+msgid "Don't boot from a volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:67
+msgid "Boot from volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:68
+msgid "Boot from volume snapshot (creates a new volume)."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:72
+#: dashboards/project/instances/workflows.py:90
+msgid "Volume Options"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:78
+#: dashboards/project/volumes/forms.py:126
+msgid "Device Name"
+msgstr "Име на устройство"
+
+#: dashboards/project/instances/workflows.py:81
+msgid "Volume mount point (e.g. 'vda' mounts at '/dev/vda')."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:83
+msgid "Delete on Terminate"
+msgstr "Изтриване при прекратяване"
+
+#: dashboards/project/instances/workflows.py:86
+msgid "Delete volume on instance terminate"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:100
+#, python-format
+msgid "Please choose a volume, or select %s."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:117
+msgid "Select Volume"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:125
+msgid "Unable to retrieve list of volumes."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:129
+msgid "Select Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:138
+msgid "Unable to retrieve list of volume snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:171
+msgid "Instance Source"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:174
+msgid "Instance Snapshot"
+msgstr "Запазено състояние на инстанция"
+
+#: dashboards/project/instances/workflows.py:178
+msgid "Size of image to launch."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:179
+msgid "Instance Count"
+msgstr "Брой на инстанции"
+
+#: dashboards/project/instances/workflows.py:182
+msgid "Number of instances to launch."
+msgstr "Колко инстанции да бъдат стартирани."
+
+#: dashboards/project/instances/workflows.py:185
+msgid "Details"
+msgstr "Детайли"
+
+#: dashboards/project/instances/workflows.py:198
+msgid ""
+"There are no image sources available; you must first create an image before "
+"attempting to launch an instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:203
+msgid "Please select an option for the instance source."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:212
+msgid ""
+"Launching multiple instances is only supported for images and instance "
+"snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:229
+msgid "Unable to retrieve public images."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:244
+msgid "Unable to retrieve images for the current project."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:267
+msgid "Select Image"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:269
+msgid "No images available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:278
+msgid "Select Instance Snapshot"
+msgstr "Изберете запазено състояние на инстанцията"
+
+#: dashboards/project/instances/workflows.py:280
+msgid "No snapshots available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:291
+msgid "Unable to retrieve instance flavors."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:304 usage/base.py:114
+msgid "Unable to retrieve quota information."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:337
+msgid "Which keypair to use for authentication."
+msgstr "Фингърпринт"
+
+#: dashboards/project/instances/workflows.py:344
+msgid "Launch instance in these security groups."
+msgstr "Стартиране на инстанция в тези групи за сигурност."
+
+#: dashboards/project/instances/workflows.py:349
+msgid ""
+"Control access to your instance via keypairs, security groups, and other "
+"mechanisms."
+msgstr ""
+"Контролирайте достъпа до вашите инстанции с ключови двойки, групи за "
+"сигурност и други механизми."
+
+#: dashboards/project/instances/workflows.py:359
+msgid "Unable to retrieve keypairs."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:361
+msgid "Select a keypair"
+msgstr "Избор на ключова двойка"
+
+#: dashboards/project/instances/workflows.py:363
+msgid "No keypairs available."
+msgstr "Няма налични ключови двойки."
+
+#: dashboards/project/instances/workflows.py:372
+msgid "Unable to retrieve list of security groups"
+msgstr "Листът с групите за сигурност не може да бъде показан"
+
+#: dashboards/project/instances/workflows.py:392
+msgid "Customization Script"
+msgstr "парола"
+
+#: dashboards/project/instances/workflows.py:394
+msgid ""
+"A script or set of commands to be executed after the instance has been built "
+"(max 16kb)."
+msgstr ""
+"Скрипт или набор от команди ще бъде изпълнен след създаването на инстанцията "
+"(максимум 16kb)."
+
+#: dashboards/project/instances/workflows.py:401
+msgid "Post-Creation"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:415
+msgid "Launch instance withthese networks"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:419
+msgid "Networking"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:421
+msgid "Select networks for your instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:433
+msgid "Unable to retrieve networks."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:456
+#, python-format
+msgid "Launched %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:457
+#, python-format
+msgid "Unable to launch %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:470
+#, python-format
+msgid "%s instances"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:473
+msgid "instance"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:4
+msgid "Instance Console Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:7
+msgid "Log Length"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:9
+msgid "Go"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:11
+msgid "View Full Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:3
+msgid "Instance Overview"
+msgstr "Преглед на инстанция"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:27
+msgid "VCPU"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:28
+#: usage/tables.py:20
+msgid "Disk"
+msgstr "Диск"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:34
+msgid "IP Addresses"
+msgstr "IP адреси"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:59
+msgid "No rules defined."
+msgstr "Няма зададени правила."
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:68
+msgid "Meta"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:71
+msgid "Key Name"
+msgstr "Име на ключ"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:84
+msgid "Volumes Attached"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:88
+#: dashboards/project/volumes/tables.py:167
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:38
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:45
+msgid "Attached To"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:90
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:42
+msgid "on"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:94
+msgid "No volumes attached."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:3
+msgid "Instance VNC Console"
+msgstr "VNC конзола на инстанцията"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid ""
+"If VNC console is not responding to keyboard input: click the grey status "
+"bar below."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid "Click here to show only VNC"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:8
+msgid "VNC console is currently unavailabe. Please try again later."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:9
+msgid "Reload"
+msgstr "Презареждане"
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:2
+msgid ""
+"You can customize your instance after it's launched using the options "
+"available here."
+msgstr ""
+"Можете да персонализирате вашата инстанция след като е стартирана "
+"използвайки настройките."
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:3
+msgid ""
+"The \"Customization Script\" field is analogous to \"User Data\" in other "
+"systems."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:3
+msgid "Specify the details for launching an instance."
+msgstr "Посочете детайлите за стартиране на инстанция."
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:4
+msgid ""
+"The chart below shows the resources used by this project in relation to the "
+"project's quotas."
+msgstr ""
+"Графиката по-долу показва ресурсите използвани от този проект в връзка с "
+"квотите на проекта."
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:6
+msgid "Flavor Details"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+msgid "Total Disk"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "MB"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:21
+msgid "Number of Instances"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:29
+msgid "Number of VCPUs"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "Total RAM"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_volumes_help.html:3
+msgid ""
+"An instance can be launched with varying types of attached storage. You may "
+"select from those options here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_update.html:17
+msgid "You may update the editable properties of your instance here."
+msgstr "Тук можете да обновите редактиращите се свойства на вашата инстанция."
+
+#: dashboards/project/instances/templates/instances/detail.html:3
+msgid "Instance Detail"
+msgstr "Детайли на инстанцията"
+
+#: dashboards/project/instances/templates/instances/update.html:3
+#: dashboards/project/instances/templates/instances/update.html:6
+msgid "Update Instance"
+msgstr "Обновяване на инстанцията"
+
+#: dashboards/project/networks/tables.py:81
+msgid "Add Subnet"
+msgstr ""
+
+#: dashboards/project/networks/views.py:86
+msgid "Unable to retrieve network details."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:37
+msgid "Network Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:42
+msgid ""
+"From here you can create a new network.\n"
+"In addition a subnet associated with the network can be created in the next "
+"panel."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:56
+msgid "Subnet Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:61
+#: dashboards/project/networks/subnets/forms.py:48
+msgid "Network address in CIDR format (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:67
+msgid "Gateway IP (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:70
+#: dashboards/project/networks/subnets/forms.py:57
+#: dashboards/project/networks/subnets/forms.py:107
+msgid "IP address of Gateway (e.g. 192.168.0.1)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:77
+msgid ""
+"You can create a subnet associated with the new network, in which case "
+"\"Network Address\" must be specified. If you wish to create a network "
+"WITHOUT a subnet, uncheck the \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:89
+msgid "Specify \"Network Address\" or clear \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:94
+#: dashboards/project/networks/subnets/forms.py:70
+msgid "Network Address and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:98
+#: dashboards/project/networks/subnets/forms.py:74
+#: dashboards/project/networks/subnets/forms.py:119
+msgid "Gateway IP and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:112
+msgid "Create"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:113
+#, python-format
+msgid "Created network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:114
+#, python-format
+msgid "Unable to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:130
+#, python-format
+msgid "Network \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:133
+#, python-format
+msgid "Failed to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:152
+#, python-format
+msgid "Subnet \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:155
+#, python-format
+msgid "Failed to create subnet \"%(sub)s\" for network \"%(net)s\"."
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Attached"
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Detached"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:85
+#, python-format
+msgid "Subnet %s was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:90
+#, python-format
+msgid "Failed to create subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:131
+#, python-format
+msgid "Subnet %s was successfully updated."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:136
+#, python-format
+msgid "Failed to update subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/tabs.py:42
+msgid "Unable to retrieve subnet details."
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/_detail_overview.html:3
+msgid "Network Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/detail.html:6
+msgid "Network Detail: "
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:3
+msgid "Port Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:17
+msgid "Fixed IP"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:21
+msgid "IP address:"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:22
+msgid "Subnet ID"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:28
+msgid "Mac Address"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/detail.html:3
+#: dashboards/project/networks/templates/networks/ports/detail.html:6
+msgid "Port Detail"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:3
+msgid "Subnet Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:21
+msgid "IP allocation pool"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:24
+msgid "Start"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:25
+msgid " - End"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/detail.html:3
+#: dashboards/project/networks/templates/networks/subnets/detail.html:6
+msgid "Subnet Detail"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:29
+msgid "Size (GB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:30
+msgid "Use snapshot as a source"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:49
+#, python-format
+msgid "Volume size must be equal to or greater than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:54
+msgid "Unable to load the specified snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:59
+msgid "Choose a snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:83
+#, python-format
+msgid "The volume size cannot be less than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:92
+#, python-format
+msgid ""
+"A volume of %(req)iGB cannot be created as you only have %(avail)iGB of your "
+"quota available."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:99
+msgid "You are already using all of your available volumes."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:115
+msgid "Unable to create volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:123
+msgid "Attach to Instance"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:124
+msgid "Select an instance to attach to."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:168
+msgid "Unknown instance (None)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:179
+#, python-format
+msgid "Attaching volume %(vol)s to instance %(inst)s on %(dev)s."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:188
+msgid "Unable to attach volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:212
+#, python-format
+msgid "Creating volume snapshot \"%s\""
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:218
+msgid "Unable to create volume snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:46
+#, python-format
+msgid "Unable to delete volume \"%s\". One or more snapshots depend on it."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:66
+msgid "Edit Attachments"
+msgstr "Редактиране на прикачените файлове"
+
+#: dashboards/project/volumes/tables.py:93
+#, python-format
+msgid "%sGB"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:106
+#: dashboards/project/volumes/views.py:149
+msgid "Unable to retrieve attachment information."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:123
+#, python-format
+msgid "Attached to %(instance)s on %(dev)s"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:180
+msgid "Detach"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:181
+msgid "Detaching"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:216
+#, python-format
+msgid "%(dev)s on instance %(instance_name)s"
+msgstr ""
+
+#: dashboards/project/volumes/tabs.py:42
+msgid "Unable to retrieve volume details."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:50
+msgid "Unable to retrieve volume list."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:58
+msgid "Unable to retrieve volume/instance attachment information"
+msgstr ""
+
+#: dashboards/project/volumes/views.py:130
+#: dashboards/project/volumes/views.py:140
+msgid "Unable to retrieve volume information."
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:9
+#: dashboards/project/volumes/templates/volumes/attach.html:6
+msgid "Manage Volume Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:13
+msgid "Attach To Instance"
+msgstr "Закачи за инстанция"
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:22
+msgid "Attach Volume"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:20
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:18
+msgid "Volumes are block devices that can be attached to instances."
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:22
+msgid "Volume Quotas"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:25
+msgid "Total Gigabytes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:34
+msgid "Number of Volumes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:8
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:23
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:3
+msgid "Create Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:3
+msgid "Volume Overview"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:34
+msgid "Attachments"
+msgstr "Прикачени файлове"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:46
+msgid "Not attached"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/create.html:6
+msgid "Create a Volume"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:6
+msgid "Create a Volume Snapshot"
+msgstr ""
+
+#: dashboards/settings/dashboard.py:24 templates/_header.html:4
+msgid "Settings"
+msgstr "Настройки"
+
+#: dashboards/settings/ec2/forms.py:36 dashboards/settings/project/forms.py:36
+msgid "Select a Project"
+msgstr "Изберете проект"
+
+#: dashboards/settings/ec2/forms.py:46
+msgid "Unable to retrieve tenant list."
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:88
+msgid "Unable to fetch EC2 credentials."
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:101
+#, python-format
+msgid "Error writing zipfile: %(exc)s"
+msgstr "Грешка при записването на zip файл: %(exc)s"
+
+#: dashboards/settings/ec2/panel.py:25
+msgid "EC2 Credentials"
+msgstr ""
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:8
+#: dashboards/settings/ec2/templates/ec2/download_form.html:23
+#: dashboards/settings/ec2/templates/ec2/index.html:3
+#: dashboards/settings/ec2/templates/ec2/index.html:6
+msgid "Download EC2 Credentials"
+msgstr ""
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:18
+msgid ""
+"Clicking \"Download EC2 Credentials\" will download a zip file which "
+"includes an rc file with your access/secret keys, as well as your x509 "
+"private key and certificate."
+msgstr ""
+
+#: dashboards/settings/project/forms.py:71
+#, python-format
+msgid "Error Downloading RC File: %s"
+msgstr "Грешка при свалянето на RC файл: %s"
+
+#: dashboards/settings/project/panel.py:25
+#: dashboards/settings/project/templates/project/_openrc.html:8
+#: dashboards/settings/project/templates/project/settings.html:3
+#: dashboards/settings/project/templates/project/settings.html:6
+msgid "OpenStack API"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:27
+msgid "Service Name"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:29
+msgid "Service Endpoint"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:33
+msgid "API Endpoints"
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:15
+msgid "Download OpenStack RC File"
+msgstr "Сваляне на OpenStack RC файл"
+
+#: dashboards/settings/project/templates/project/_openrc.html:25
+msgid ""
+"Download the RC file for the selected project, then type \"source openrc\" "
+"in the terminal to configure your environment to communicate with OpenStack."
+msgstr ""
+"Свалете RC файла за избрания проект, после напишете \"source openrc\" в "
+"терминала за да конфигурирате вашата среда да комуникира с OpenStack."
+
+#: dashboards/settings/project/templates/project/_openrc.html:30
+msgid "Download RC File"
+msgstr "Сваляне на RC файл"
+
+#: dashboards/settings/user/forms.py:57
+msgid "Settings saved."
+msgstr ""
+
+#: dashboards/settings/user/panel.py:25
+#: dashboards/settings/user/templates/user/_settings.html:8
+#: dashboards/settings/user/templates/user/settings.html:3
+#: dashboards/settings/user/templates/user/settings.html:6
+msgid "User Settings"
+msgstr "Потребителски настройки"
+
+#: dashboards/settings/user/templates/user/_settings.html:18
+msgid "From here you can modify dashboard settings for your user."
+msgstr ""
+
#: templates/403.html:4 templates/403.html.py:9
msgid "Forbidden"
msgstr "Забранено"
@@ -83,10 +3256,6 @@ msgstr "Забранено"
msgid "Home"
msgstr "Начало"
-#: templates/403.html:24 templates/404.html:23 templates/500.html:23
-msgid "Projects"
-msgstr "Проекти"
-
#: templates/404.html:4
msgid "Page Not Found"
msgstr "Страницата не беше намерена"
@@ -110,3 +3279,48 @@ msgid ""
msgstr ""
"Възникна неочаквана грешка при обработката на заявката Ви. Моля, опитайте "
"отново."
+
+#: templates/_header.html:3
+msgid "Logged in as"
+msgstr ""
+
+#: templates/_header.html:6
+msgid "Help"
+msgstr ""
+
+#: templates/_header.html:8
+msgid "Sign Out"
+msgstr ""
+
+#: test/settings.py:50
+msgid "Password must be between 8 and 18 characters."
+msgstr "Паролата трябва да е между 8 и 18 символа."
+
+#: usage/base.py:97
+msgid "Unable to retrieve usage information."
+msgstr "Информацията за потреблението не може да бъде получена."
+
+#: usage/base.py:100
+msgid "You are viewing data for the future, which may or may not exist."
+msgstr ""
+"Вие разглеждате данни за в бъдеще, които могат или не могат да съществуват."
+
+#: usage/tables.py:11
+msgid "Download CSV Summary"
+msgstr ""
+
+#: usage/tables.py:25
+msgid "VCPU Hours"
+msgstr ""
+
+#: usage/tables.py:32
+msgid "Disk GB Hours"
+msgstr ""
+
+#: usage/tables.py:40 usage/tables.py:68
+msgid "Usage Summary"
+msgstr "Обобщение на потреблението"
+
+#: usage/tables.py:60
+msgid "Uptime"
+msgstr ""
diff --git a/openstack_dashboard/locale/cs/LC_MESSAGES/django.mo b/openstack_dashboard/locale/cs/LC_MESSAGES/django.mo
index adb9790bc..5991903f6 100644
--- a/openstack_dashboard/locale/cs/LC_MESSAGES/django.mo
+++ b/openstack_dashboard/locale/cs/LC_MESSAGES/django.mo
Binary files differ
diff --git a/openstack_dashboard/locale/cs/LC_MESSAGES/django.po b/openstack_dashboard/locale/cs/LC_MESSAGES/django.po
index 83b7cddc6..878cc8791 100644
--- a/openstack_dashboard/locale/cs/LC_MESSAGES/django.po
+++ b/openstack_dashboard/locale/cs/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Horizon\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-09-18 22:18+0000\n"
+"POT-Creation-Date: 2012-10-05 19:30+0000\n"
"PO-Revision-Date: 2012-08-28 09:43+0000\n"
"Last-Translator: jui <appukonrad@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,63 +18,3227 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
-#: settings.py:141
+#: settings.py:142
msgid "Bulgarian (Bulgaria)"
msgstr ""
-#: settings.py:142
+#: settings.py:143
msgid "Czech"
msgstr ""
-#: settings.py:143
+#: settings.py:144
msgid "English"
msgstr "Anglicky"
-#: settings.py:144
+#: settings.py:145
msgid "Spanish"
msgstr "Španělsky"
-#: settings.py:145
+#: settings.py:146
msgid "French"
msgstr "Francouzsky"
-#: settings.py:146
+#: settings.py:147
msgid "Italiano"
msgstr "Italsky"
-#: settings.py:147
+#: settings.py:148
msgid "Japanese"
msgstr "Japonsky"
-#: settings.py:148
+#: settings.py:149
msgid "Korean (Korea)"
msgstr ""
-#: settings.py:149
+#: settings.py:150
msgid "Dutch (Netherlands)"
msgstr ""
-#: settings.py:150
+#: settings.py:151
msgid "Polish"
msgstr "Polsky"
-#: settings.py:151
+#: settings.py:152
msgid "Portuguese"
msgstr "Portugalsky"
-#: settings.py:152
+#: settings.py:153
#, fuzzy
msgid "Portuguese (Brazil)"
msgstr "Portugalsky"
-#: settings.py:153
+#: settings.py:154
msgid "Simplified Chinese"
msgstr "Zjednodušená Čínština"
-#: settings.py:154
+#: settings.py:155
msgid "Traditional Chinese"
msgstr "Tradiční Čínština"
+#: api/keystone.py:56
+#, python-format
+msgid "%(type)s (%(backend)s backend)"
+msgstr ""
+
+#: api/nova.py:191
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(group)s"
+msgstr ""
+
+#: api/nova.py:196
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(cidr)s"
+msgstr ""
+
+#: api/nova.py:532
+msgid "Unknown instance"
+msgstr ""
+
+#: api/swift.py:217
+msgid "Unicode is not currently supported for object copy."
+msgstr ""
+
+#: dashboards/admin/dashboard.py:24
+msgid "System Panel"
+msgstr ""
+
+#: dashboards/admin/dashboard.py:30
+msgid "Admin"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:36 dashboards/admin/networks/forms.py:34
+#: dashboards/admin/networks/forms.py:69
+#: dashboards/admin/networks/ports/forms.py:40
+#: dashboards/admin/networks/ports/forms.py:72
+#: dashboards/admin/networks/ports/tables.py:73
+#: dashboards/admin/networks/subnets/tables.py:70
+#: dashboards/admin/projects/tables.py:87
+#: dashboards/admin/projects/workflows.py:71
+#: dashboards/admin/services/tables.py:38
+#: dashboards/admin/volumes/tables.py:10
+#: dashboards/project/access_and_security/security_groups/forms.py:36
+#: dashboards/project/access_and_security/security_groups/tables.py:58
+#: dashboards/project/images_and_snapshots/images/forms.py:40
+#: dashboards/project/images_and_snapshots/images/forms.py:115
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:9
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:10
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:77
+#: dashboards/project/instances/templates/instances/_detail_overview.html:9
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:9
+#: dashboards/project/networks/forms.py:37
+#: dashboards/project/networks/tables.py:94
+#: dashboards/project/networks/ports/tables.py:40
+#: dashboards/project/networks/subnets/forms.py:43
+#: dashboards/project/networks/subnets/forms.py:102
+#: dashboards/project/networks/subnets/tables.py:82
+#: dashboards/project/networks/templates/networks/_detail_overview.html:7
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:9
+#: dashboards/project/volumes/tables.py:144
+#: dashboards/project/volumes/tables.py:164
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:9
+msgid "Name"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:37 dashboards/admin/flavors/tables.py:41
+#: dashboards/admin/projects/workflows.py:39
+#: dashboards/project/instances/templates/instances/_detail_overview.html:26
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:10
+#: usage/tables.py:19
+msgid "VCPUs"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:38
+msgid "RAM MB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:39
+msgid "Root Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:40
+msgid "Ephemeral Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:50
+msgid "Unable to get unique ID for new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:67
+#, python-format
+msgid "Created flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:71
+msgid "Unable to create flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:92
+#, python-format
+msgid "Updated flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:96
+msgid "Unable to update flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/panel.py:29 dashboards/admin/flavors/tables.py:15
+#: dashboards/admin/flavors/tables.py:52
+#: dashboards/admin/flavors/templates/flavors/index.html:3
+#: dashboards/admin/flavors/templates/flavors/index.html:6
+msgid "Flavors"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:14
+#: dashboards/project/instances/workflows.py:177
+#: dashboards/project/instances/templates/instances/_detail_overview.html:22
+msgid "Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:23
+#: dashboards/admin/flavors/templates/flavors/_create.html:8
+#: dashboards/admin/flavors/templates/flavors/_create.html:23
+#: dashboards/admin/flavors/templates/flavors/create.html:3
+#: dashboards/admin/flavors/templates/flavors/create.html:6
+msgid "Create Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:30
+#: dashboards/admin/flavors/templates/flavors/_edit.html:8
+#: dashboards/admin/flavors/templates/flavors/edit.html:3
+#: dashboards/admin/flavors/templates/flavors/edit.html:6
+msgid "Edit Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:36
+#, python-format
+msgid "%sMB"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:40
+msgid "Flavor Name"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:43
+#: dashboards/project/instances/templates/instances/_detail_overview.html:24
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: usage/tables.py:22
+msgid "RAM"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:45
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+msgid "Root Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:47
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+msgid "Ephemeral Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:49
+msgid "Unable to retrieve flavor list."
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:76
+msgid "Unable to retrieve flavor data."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:17
+#: dashboards/admin/flavors/templates/flavors/_edit.html:17
+#: dashboards/admin/images/templates/images/_update.html:17
+#: dashboards/admin/networks/templates/networks/_create.html:17
+#: dashboards/admin/networks/templates/networks/ports/_create.html:17
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:17
+#: dashboards/admin/projects/tables.py:89
+#: dashboards/admin/projects/workflows.py:74
+#: dashboards/admin/projects/templates/projects/_add_user.html:17
+#: dashboards/admin/projects/templates/projects/_create.html:17
+#: dashboards/admin/projects/templates/projects/_create_user.html:17
+#: dashboards/admin/projects/templates/projects/_quotas.html:16
+#: dashboards/admin/projects/templates/projects/_update.html:17
+#: dashboards/admin/users/templates/users/_create.html:16
+#: dashboards/admin/users/templates/users/_update.html:16
+#: dashboards/project/access_and_security/security_groups/forms.py:38
+#: dashboards/project/access_and_security/security_groups/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:17
+#: dashboards/project/containers/templates/containers/_copy.html:16
+#: dashboards/project/containers/templates/containers/_create.html:16
+#: dashboards/project/containers/templates/containers/_upload.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/_create.html:16
+#: dashboards/project/networks/templates/networks/subnets/_create.html:17
+#: dashboards/project/volumes/forms.py:28
+#: dashboards/project/volumes/forms.py:195
+#: dashboards/project/volumes/tables.py:147
+#: dashboards/project/volumes/templates/volumes/_create.html:18
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:17
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:14
+msgid "Description"
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:18
+msgid "From here you can define the sizing of a new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:24
+#: dashboards/admin/flavors/templates/flavors/_edit.html:25
+#: dashboards/admin/images/templates/images/_update.html:24
+#: dashboards/admin/networks/templates/networks/_create.html:24
+#: dashboards/admin/networks/templates/networks/_update.html:23
+#: dashboards/admin/networks/templates/networks/ports/_create.html:24
+#: dashboards/admin/networks/templates/networks/ports/_update.html:28
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:24
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:32
+#: dashboards/admin/projects/templates/projects/_add_user.html:24
+#: dashboards/admin/projects/templates/projects/_create.html:24
+#: dashboards/admin/projects/templates/projects/_create_user.html:24
+#: dashboards/admin/projects/templates/projects/_quotas.html:23
+#: dashboards/admin/projects/templates/projects/_update.html:24
+#: dashboards/admin/users/templates/users/_create.html:23
+#: dashboards/admin/users/templates/users/_update.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:32
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:20
+#: dashboards/project/containers/templates/containers/_copy.html:23
+#: dashboards/project/containers/templates/containers/_create.html:23
+#: dashboards/project/containers/templates/containers/_upload.html:24
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:32
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:24
+#: dashboards/project/instances/templates/instances/_update.html:23
+#: dashboards/project/networks/templates/networks/_create.html:23
+#: dashboards/project/networks/templates/networks/_update.html:23
+#: dashboards/project/networks/templates/networks/subnets/_create.html:24
+#: dashboards/project/networks/templates/networks/subnets/_update.html:32
+#: dashboards/project/volumes/templates/volumes/_attach.html:24
+#: dashboards/project/volumes/templates/volumes/_create.html:56
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:24
+#: dashboards/settings/ec2/templates/ec2/download_form.html:24
+#: dashboards/settings/project/templates/project/_openrc.html:31
+#: dashboards/settings/user/templates/user/_settings.html:24
+msgid "Cancel"
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:18
+msgid "From here you can alter the sizing of the current flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:19
+msgid ""
+"Note: this will not affect the resources allocated to any existing instances "
+"using this flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:24
+#: dashboards/admin/projects/workflows.py:270
+#: dashboards/settings/user/templates/user/_settings.html:23
+msgid "Save"
+msgstr ""
+
+#: dashboards/admin/images/panel.py:29 dashboards/admin/images/tables.py:44
+#: dashboards/admin/images/templates/images/index.html:3
+#: dashboards/admin/images/templates/images/index.html:6
+#: dashboards/project/images_and_snapshots/images/tables.py:47
+#: dashboards/project/images_and_snapshots/images/tables.py:132
+msgid "Images"
+msgstr ""
+
+#: dashboards/admin/images/tables.py:40
+#: dashboards/project/images_and_snapshots/images/tables.py:113
+#: dashboards/project/instances/templates/instances/_detail_overview.html:74
+msgid "Image Name"
+msgstr ""
+
+#: dashboards/admin/images/views.py:55
+msgid "Unable to retrieve image list."
+msgstr ""
+
+#: dashboards/admin/images/templates/images/_update.html:8
+#: dashboards/admin/images/templates/images/_update.html:23
+#: dashboards/admin/images/templates/images/update.html:4
+#: dashboards/admin/images/templates/images/update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:22
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:6
+msgid "Update Image"
+msgstr ""
+
+#: dashboards/admin/images/templates/images/_update.html:18
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:17
+msgid "From here you can modify different properties of an image."
+msgstr ""
+
+#: dashboards/admin/instances/panel.py:29
+#: dashboards/admin/instances/tables.py:94
+#: dashboards/admin/instances/templates/instances/index.html:3
+#: dashboards/admin/projects/workflows.py:40
+#: dashboards/project/instances/panel.py:25
+#: dashboards/project/instances/tables.py:70
+#: dashboards/project/instances/tables.py:90
+#: dashboards/project/instances/tables.py:107
+#: dashboards/project/instances/tables.py:136
+#: dashboards/project/instances/tables.py:313
+#: dashboards/project/instances/templates/instances/index.html:3
+#: dashboards/project/instances/templates/instances/index.html:6
+msgid "Instances"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:60 usage/tables.py:30
+#, fuzzy
+msgid "Project Name"
+msgstr "Projekty"
+
+#: dashboards/admin/instances/tables.py:67
+#: dashboards/admin/services/tables.py:40
+msgid "Host"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:71
+#: dashboards/project/instances/tables.py:290
+#: dashboards/project/instances/workflows.py:176 usage/tables.py:57
+msgid "Instance Name"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:72
+#: dashboards/project/access_and_security/floating_ips/tables.py:111
+#: dashboards/project/access_and_security/floating_ips/workflows.py:32
+#: dashboards/project/access_and_security/floating_ips/workflows.py:39
+#: dashboards/project/instances/tables.py:291
+msgid "IP Address"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:74
+#: dashboards/project/containers/tables.py:256
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:30
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:37
+#: dashboards/project/instances/tables.py:293
+#: dashboards/project/volumes/tables.py:150
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:26
+msgid "Size"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:79
+#: dashboards/admin/networks/tables.py:74
+#: dashboards/admin/networks/ports/tables.py:77
+#: dashboards/project/images_and_snapshots/images/tables.py:119
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:13
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:18
+#: dashboards/project/instances/tables.py:298
+#: dashboards/project/instances/templates/instances/_detail_overview.html:13
+#: dashboards/project/networks/tables.py:100
+#: dashboards/project/networks/ports/tables.py:44
+#: dashboards/project/networks/templates/networks/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:30
+#: dashboards/project/volumes/tables.py:154
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:17
+msgid "Status"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:83
+#: dashboards/project/instances/tables.py:302
+msgid "Task"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:90
+#: dashboards/project/instances/tables.py:309
+msgid "Power State"
+msgstr ""
+
+#: dashboards/admin/instances/views.py:49
+#: dashboards/project/access_and_security/views.py:76
+#: dashboards/project/access_and_security/floating_ips/workflows.py:65
+msgid "Unable to retrieve instance list."
+msgstr ""
+
+#: dashboards/admin/instances/views.py:63
+#: dashboards/admin/networks/views.py:48
+msgid "Unable to retrieve instance tenant information."
+msgstr ""
+
+#: dashboards/admin/instances/views.py:80
+#: dashboards/project/instances/views.py:82
+msgid "Unable to retrieve instance size information."
+msgstr ""
+
+#: dashboards/admin/instances/templates/instances/index.html:6
+msgid "All Instances"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:36
+#: dashboards/admin/networks/tables.py:67
+#: dashboards/admin/projects/tables.py:65 dashboards/project/dashboard.py:40
+#: dashboards/project/instances/workflows.py:38
+#, fuzzy
+msgid "Project"
+msgstr "Projekty"
+
+#: dashboards/admin/networks/forms.py:37 dashboards/admin/networks/forms.py:74
+#: dashboards/admin/networks/tables.py:72
+#: dashboards/project/networks/tables.py:98
+#: dashboards/project/networks/templates/networks/_detail_overview.html:17
+msgid "Shared"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:46 dashboards/admin/users/forms.py:42
+msgid "Select a project"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:58
+#, python-format
+msgid "Network %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:64
+#, python-format
+msgid "Failed to create network %s"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:71
+#: dashboards/admin/networks/templates/networks/ports/_update.html:12
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:12
+#: dashboards/admin/users/forms.py:114
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:11
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:12
+#: dashboards/project/instances/templates/instances/_detail_overview.html:11
+#: dashboards/project/networks/forms.py:39
+#: dashboards/project/networks/templates/networks/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_update.html:12
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:11
+msgid "ID"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:82
+#: dashboards/project/networks/forms.py:48
+#, python-format
+msgid "Network %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:87
+#: dashboards/project/networks/forms.py:53
+#, python-format
+msgid "Failed to update network %s"
+msgstr ""
+
+#: dashboards/admin/networks/panel.py:25
+#: dashboards/admin/networks/tables.py:35
+#: dashboards/admin/networks/tables.py:80
+#: dashboards/admin/networks/templates/networks/index.html:3
+#: dashboards/admin/networks/templates/networks/index.html:6
+#: dashboards/project/instances/workflows.py:412
+#: dashboards/project/networks/panel.py:25
+#: dashboards/project/networks/tables.py:44
+#: dashboards/project/networks/tables.py:106
+#: dashboards/project/networks/templates/networks/index.html:3
+#: dashboards/project/networks/templates/networks/index.html:6
+msgid "Networks"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:34
+#: dashboards/project/networks/tables.py:43
+#: dashboards/project/networks/templates/networks/subnets/index.html:3
+#: dashboards/project/networks/templates/networks/subnets/index.html:6
+msgid "Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:41
+#: dashboards/project/networks/tables.py:59
+#, python-format
+msgid "Failed to delete network %s"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:49
+#: dashboards/admin/networks/templates/networks/_create.html:8
+#: dashboards/admin/networks/templates/networks/_create.html:23
+#: dashboards/admin/networks/templates/networks/create.html:3
+#: dashboards/admin/networks/templates/networks/create.html:6
+#: dashboards/project/networks/tables.py:67
+#: dashboards/project/networks/workflows.py:111
+#: dashboards/project/networks/templates/networks/_create.html:7
+#: dashboards/project/networks/templates/networks/_create.html:22
+#: dashboards/project/networks/templates/networks/create.html:3
+#: dashboards/project/networks/templates/networks/create.html:6
+msgid "Create Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:56
+#: dashboards/admin/networks/templates/networks/_update.html:7
+#: dashboards/project/networks/tables.py:74
+#: dashboards/project/networks/templates/networks/_update.html:7
+msgid "Edit Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:68
+#: dashboards/admin/networks/ports/forms.py:33
+#: dashboards/project/networks/subnets/forms.py:35
+msgid "Network Name"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:71
+#: dashboards/project/networks/tables.py:97
+msgid "Subnets Associated"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:76
+#: dashboards/admin/networks/ports/tables.py:79
+#: dashboards/project/networks/tables.py:102
+#: dashboards/project/networks/ports/tables.py:46
+#: dashboards/project/networks/templates/networks/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:32
+msgid "Admin State"
+msgstr ""
+
+#: dashboards/admin/networks/views.py:60
+#: dashboards/project/networks/views.py:52
+msgid "Network list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:91
+#: dashboards/project/networks/views.py:109
+msgid "Subnet list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:103
+#: dashboards/project/networks/views.py:121
+msgid "Port list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:118
+#: dashboards/project/networks/views.py:134
+#: dashboards/project/networks/subnets/tables.py:96
+#, python-format
+msgid "Unable to retrieve details for network \"%s\"."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:36
+#: dashboards/project/networks/subnets/forms.py:39
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:13
+msgid "Network ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:42
+#: dashboards/admin/networks/ports/forms.py:74
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:34
+msgid "Device ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:54
+#, python-format
+msgid "Port %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:59
+#, python-format
+msgid "Failed to create a port for network %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:84
+#, python-format
+msgid "Port %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:89
+#, python-format
+msgid "Failed to update port %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:34
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:6
+msgid "Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:35
+#: dashboards/admin/networks/ports/tables.py:83
+#: dashboards/project/networks/ports/tables.py:53
+#, fuzzy
+msgid "Ports"
+msgstr "Portugalsky"
+
+#: dashboards/admin/networks/ports/tables.py:41
+#: dashboards/admin/networks/subnets/tables.py:39
+#: dashboards/project/networks/subnets/tables.py:51
+#, python-format
+msgid "Failed to delete subnet %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:51
+#: dashboards/admin/networks/templates/networks/ports/_create.html:8
+#: dashboards/admin/networks/templates/networks/ports/_create.html:23
+#: dashboards/admin/networks/templates/networks/ports/create.html:3
+#: dashboards/admin/networks/templates/networks/ports/create.html:6
+msgid "Create Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:62
+#: dashboards/admin/networks/templates/networks/ports/_update.html:7
+msgid "Edit Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:75
+#: dashboards/project/networks/ports/tables.py:42
+msgid "Fixed IPs"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:76
+#: dashboards/project/networks/ports/tables.py:43
+msgid "Device Attached"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tabs.py:32
+#: dashboards/admin/overview/panel.py:29
+#: dashboards/admin/overview/templates/overview/usage.html:6
+#: dashboards/project/images_and_snapshots/images/tabs.py:27
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:27
+#: dashboards/project/instances/tabs.py:26
+#: dashboards/project/networks/ports/tabs.py:32
+#: dashboards/project/networks/subnets/tabs.py:32
+#: dashboards/project/overview/panel.py:29
+#: dashboards/project/overview/templates/overview/usage.html:6
+#: dashboards/project/volumes/tabs.py:27
+msgid "Overview"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tabs.py:42
+#: dashboards/project/networks/ports/tabs.py:42
+msgid "Unable to retrieve port details."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:49
+#: dashboards/admin/networks/subnets/views.py:49
+#: dashboards/project/networks/subnets/views.py:54
+msgid "Unable to retrieve network."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:82
+msgid "Unable to retrieve port details"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/forms.py:43
+#, python-format
+msgid "Failed to retrieve network %s for a subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:32
+#: dashboards/project/networks/subnets/tables.py:44
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:6
+msgid "Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:33
+#: dashboards/admin/networks/subnets/tables.py:81
+#: dashboards/project/networks/subnets/tables.py:45
+#: dashboards/project/networks/subnets/tables.py:104
+msgid "Subnets"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:49
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:8
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:23
+#: dashboards/admin/networks/templates/networks/subnets/create.html:3
+#: dashboards/admin/networks/templates/networks/subnets/create.html:6
+#: dashboards/project/networks/workflows.py:53
+#: dashboards/project/networks/subnets/tables.py:61
+#: dashboards/project/networks/templates/networks/subnets/_create.html:8
+#: dashboards/project/networks/templates/networks/subnets/_create.html:23
+#: dashboards/project/networks/templates/networks/subnets/create.html:3
+#: dashboards/project/networks/templates/networks/subnets/create.html:6
+msgid "Create Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:60
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:7
+#: dashboards/project/networks/subnets/tables.py:72
+#: dashboards/project/networks/templates/networks/subnets/_update.html:7
+msgid "Edit Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:72
+#: dashboards/project/access_and_security/security_groups/forms.py:91
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:15
+msgid "CIDR"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:73
+#: dashboards/project/networks/workflows.py:66
+#: dashboards/project/networks/subnets/forms.py:53
+#: dashboards/project/networks/subnets/tables.py:85
+msgid "IP Version"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:74
+#: dashboards/project/networks/subnets/forms.py:54
+#: dashboards/project/networks/subnets/forms.py:104
+#: dashboards/project/networks/subnets/tables.py:86
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:19
+msgid "Gateway IP"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/views.py:82
+#: dashboards/project/networks/subnets/views.py:86
+msgid "Unable to retrieve subnet details"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_create.html:18
+#: dashboards/project/networks/templates/networks/_create.html:17
+msgid "Select a name for your network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:16
+#: dashboards/admin/networks/templates/networks/ports/_update.html:21
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:25
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:17
+#: dashboards/project/instances/templates/instances/_update.html:16
+#: dashboards/project/networks/templates/networks/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_update.html:25
+#: dashboards/settings/ec2/templates/ec2/download_form.html:17
+#: dashboards/settings/project/templates/project/_openrc.html:24
+#: dashboards/settings/user/templates/user/_settings.html:17
+msgid "Description:"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:17
+#: dashboards/project/networks/templates/networks/_update.html:17
+msgid "You may update the editable properties of your network here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:22
+#: dashboards/admin/networks/templates/networks/ports/_update.html:27
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:31
+#: dashboards/project/instances/templates/instances/_update.html:22
+#: dashboards/project/networks/templates/networks/_update.html:22
+#: dashboards/project/networks/templates/networks/subnets/_update.html:31
+msgid "Save Changes"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/update.html:3
+#: dashboards/admin/networks/templates/networks/update.html:6
+#: dashboards/project/networks/templates/networks/update.html:3
+#: dashboards/project/networks/templates/networks/update.html:6
+msgid "Update Network"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_create.html:18
+msgid ""
+"You can create a port for the network. If you specify device ID to be "
+"attached, the device specified will be attached to the port created."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_update.html:22
+msgid "You may update the editable properties of your port here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/update.html:3
+#: dashboards/admin/networks/templates/networks/ports/update.html:6
+msgid "Update Port"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:18
+#: dashboards/project/networks/templates/networks/subnets/_create.html:18
+msgid ""
+"You can create a subnet for the network. Any network address can be "
+"specified unless the network address does not overlap other subnets in the "
+"network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:14
+#: dashboards/project/networks/workflows.py:58
+#: dashboards/project/networks/subnets/forms.py:45
+#: dashboards/project/networks/subnets/tables.py:84
+#: dashboards/project/networks/templates/networks/subnets/_update.html:14
+msgid "Network Address"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:17
+#: dashboards/project/networks/templates/networks/subnets/_update.html:16
+msgid "IP version"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:26
+#: dashboards/project/networks/templates/networks/subnets/_update.html:26
+msgid "You may update the editable properties of your subnet here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/index.html:3
+#: dashboards/admin/networks/templates/networks/subnets/index.html:6
+#: dashboards/project/networks/templates/networks/detail.html:3
+msgid "Network Detail"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/update.html:3
+#: dashboards/admin/networks/templates/networks/subnets/update.html:6
+#: dashboards/project/networks/templates/networks/subnets/update.html:3
+#: dashboards/project/networks/templates/networks/subnets/update.html:6
+msgid "Update Subnet"
+msgstr ""
+
+#: dashboards/admin/overview/templates/overview/usage.html:3
+msgid "Usage Overview"
+msgstr ""
+
+#: dashboards/admin/overview/templates/overview/usage.html:12
+msgid "Monitoring"
+msgstr ""
+
+#: dashboards/admin/projects/panel.py:29
+#: dashboards/admin/projects/tables.py:66
+#: dashboards/admin/projects/tables.py:95
+#: dashboards/admin/projects/templates/projects/index.html:8
+#: templates/403.html:24 templates/404.html:23 templates/500.html:23
+msgid "Projects"
+msgstr "Projekty"
+
+#: dashboards/admin/projects/tables.py:19
+msgid "Modify Users"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:32
+msgid "View Usage"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:39
+#: dashboards/admin/projects/templates/projects/_create.html:8
+#: dashboards/admin/projects/templates/projects/_create.html:23
+#: dashboards/admin/projects/templates/projects/create.html:6
+#, fuzzy
+msgid "Create Project"
+msgstr "Projekty"
+
+#: dashboards/admin/projects/tables.py:46
+#: dashboards/admin/projects/workflows.py:269
+#: dashboards/admin/projects/templates/projects/update.html:3
+#: dashboards/admin/projects/templates/projects/update.html:6
+#, fuzzy
+msgid "Edit Project"
+msgstr "Projekty"
+
+#: dashboards/admin/projects/tables.py:90
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:60
+#: dashboards/project/networks/templates/networks/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:15
+#, fuzzy
+msgid "Project ID"
+msgstr "Projekty"
+
+#: dashboards/admin/projects/tables.py:91
+#: dashboards/admin/projects/workflows.py:76
+#: dashboards/admin/projects/workflows.py:251
+#: dashboards/admin/services/tables.py:42 dashboards/admin/users/tables.py:40
+#: dashboards/admin/users/tables.py:115
+msgid "Enabled"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:104
+msgid "Remove"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:105
+msgid "Removed"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:106 dashboards/admin/users/tables.py:41
+#: dashboards/admin/users/tables.py:75
+#: dashboards/project/instances/workflows.py:39
+msgid "User"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:107 dashboards/admin/users/panel.py:29
+#: dashboards/admin/users/tables.py:42 dashboards/admin/users/tables.py:76
+#: dashboards/admin/users/tables.py:122
+#: dashboards/admin/users/templates/users/index.html:8
+msgid "Users"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:125
+msgid "Unable to retrieve role information."
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:130
+msgid "Roles"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:134
+msgid "Users For Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:142
+#, fuzzy
+msgid "Add To Project"
+msgstr "Projekty"
+
+#: dashboards/admin/projects/tables.py:154
+msgid "Add New Users"
+msgstr ""
+
+#: dashboards/admin/projects/views.py:67
+msgid "Unable to retrieve project information."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:87
+msgid "Unable to retrieve project list."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:110
+msgid "Unable to retrieve users."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:154
+msgid "Unable to retrieve default quota values."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:182
+msgid "Unable to retrieve project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:37
+msgid "Injected File Content Bytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:38
+msgid "Metadata Items"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:41
+msgid "Injected Files"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:44
+#: dashboards/admin/volumes/panel.py:9 dashboards/admin/volumes/tables.py:15
+#: dashboards/admin/volumes/templates/volumes/index.html:3
+#: dashboards/admin/volumes/templates/volumes/index.html:6
+#: dashboards/project/volumes/panel.py:25
+#: dashboards/project/volumes/tables.py:38
+#: dashboards/project/volumes/tables.py:171
+#: dashboards/project/volumes/tables.py:183
+#: dashboards/project/volumes/templates/volumes/index.html:3
+#: dashboards/project/volumes/templates/volumes/index.html:6
+msgid "Volumes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:45
+msgid "Gigabytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:46
+msgid "RAM (MB)"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:47
+#: dashboards/project/access_and_security/floating_ips/tables.py:50
+#: dashboards/project/access_and_security/floating_ips/tables.py:128
+msgid "Floating IPs"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:50
+msgid "Quota"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:52
+msgid "From here you can set quotas (max limits) for the project."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:81
+#: dashboards/admin/projects/workflows.py:254
+#, fuzzy
+msgid "Project Info"
+msgstr "Projekty"
+
+#: dashboards/admin/projects/workflows.py:82
+#: dashboards/admin/projects/templates/projects/_create.html:18
+msgid "From here you can create a new project to organize users."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:101
+msgid "Unable to retrieve user list. Please try again later."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:155
+#: dashboards/admin/projects/templates/projects/_update_members.html:16
+#, fuzzy
+msgid "Project Members"
+msgstr "Projekty"
+
+#: dashboards/admin/projects/workflows.py:169
+#: dashboards/admin/users/views.py:47
+msgid "Unable to retrieve user list."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:180
+#, fuzzy
+msgid "Add Project"
+msgstr "Projekty"
+
+#: dashboards/admin/projects/workflows.py:181
+#, fuzzy
+msgid "Finish"
+msgstr "Španělsky"
+
+#: dashboards/admin/projects/workflows.py:182
+#, python-format
+msgid "Created new project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:183
+#, python-format
+msgid "Unable to create project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:227
+#, python-format
+msgid "Failed to add %s project members and set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:246
+msgid "Unable to set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:256
+msgid "From here you can edit the project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:271
+#, python-format
+msgid "Modified project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:272
+#, python-format
+msgid "Unable to modify project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:342
+#, python-format
+msgid "Failed to modify %s project members and update project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:363
+msgid ""
+"Modified project information and members, but unable to modify project "
+"quotas."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:8
+#: dashboards/admin/projects/templates/projects/add_user.html:3
+#: dashboards/admin/projects/templates/projects/add_user.html:6
+msgid "Add User To Project"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:18
+msgid "Select the user role for the project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:23
+msgid "Add"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:7
+#, python-format
+msgid "Create User for project '%(tenant_name)s'."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:18
+msgid "From here you can create a new user to add to this project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:23
+#: dashboards/admin/users/tables.py:20
+#: dashboards/admin/users/templates/users/_create.html:7
+#: dashboards/admin/users/templates/users/_create.html:22
+#: dashboards/admin/users/templates/users/create.html:7
+msgid "Create User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:7
+#: dashboards/admin/projects/templates/projects/_quotas.html:22
+msgid "Update Quota"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:17
+#, python-format
+msgid ""
+"From here you can edit quotas (max limits) for the project %(tenant.name)s."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update.html:8
+#: dashboards/admin/projects/templates/projects/_update.html:23
+#: dashboards/admin/projects/templates/projects/quotas.html:6
+#, fuzzy
+msgid "Update Project"
+msgstr "Projekty"
+
+#: dashboards/admin/projects/templates/projects/_update.html:18
+msgid "From here you can edit a project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:7
+msgid ""
+"From here you can add and remove members to this project from the list of "
+"all available users."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:10
+msgid "All Users"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:25
+#: dashboards/admin/projects/templates/projects/_update_members.html:32
+msgid "No users found."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/create_user.html:3
+#: dashboards/admin/projects/templates/projects/create_user.html:6
+msgid "Add New User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:3
+msgid "Project Usage Overview"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:7
+#, fuzzy
+msgid "Project Usage"
+msgstr "Projekty"
+
+#: dashboards/admin/projects/templates/projects/users.html:7
+msgid "Users for Project"
+msgstr ""
+
+#: dashboards/admin/quotas/panel.py:29 dashboards/admin/quotas/tables.py:36
+msgid "Quotas"
+msgstr ""
+
+#: dashboards/admin/quotas/tables.py:28
+msgid "Quota Name"
+msgstr ""
+
+#: dashboards/admin/quotas/tables.py:29
+msgid "Limit"
+msgstr ""
+
+#: dashboards/admin/quotas/views.py:46
+msgid "Unable to get quota info."
+msgstr ""
+
+#: dashboards/admin/quotas/templates/quotas/index.html:8
+msgid "Default Quotas"
+msgstr ""
+
+#: dashboards/admin/services/panel.py:29
+#: dashboards/admin/services/tables.py:47
+#: dashboards/admin/services/templates/services/index.html:8
+msgid "Services"
+msgstr ""
+
+#: dashboards/admin/services/tables.py:37
+msgid "Id"
+msgstr ""
+
+#: dashboards/admin/services/tables.py:39
+msgid "Service"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:54
+msgid "Passwords do not match."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:62 dashboards/admin/users/forms.py:115
+#: dashboards/admin/users/tables.py:108
+msgid "User Name"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:63 dashboards/admin/users/forms.py:116
+#: dashboards/admin/users/tables.py:109
+msgid "Email"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:65 dashboards/admin/users/forms.py:117
+msgid "Password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:70 dashboards/admin/users/forms.py:124
+msgid "Confirm Password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:73 dashboards/admin/users/forms.py:127
+#, fuzzy
+msgid "Primary Project"
+msgstr "Projekty"
+
+#: dashboards/admin/users/forms.py:75
+msgid "Role"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:96
+#, python-format
+msgid "User \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:106
+msgid "Unable to add userto primary project."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:110
+msgid "Unable to create user."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:151
+msgid "name"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:151
+msgid "email"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:160
+msgid "primary project"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:173
+#, python-format
+msgid "The user %s has no role defined for"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:181
+msgid "password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:190
+msgid "User has been updated successfully."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:194
+#, python-format
+msgid "Unable to update %(attributes)s for the user."
+msgstr ""
+
+#: dashboards/admin/users/tables.py:32
+#: dashboards/project/images_and_snapshots/images/tables.py:68
+msgid "Edit"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:39
+msgid "Enable"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:39
+msgid "Disable"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:40
+msgid "Disabled"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:63
+msgid "You cannot disable the user you are currently logged in as."
+msgstr ""
+
+#: dashboards/admin/users/tables.py:114
+msgid "User ID"
+msgstr ""
+
+#: dashboards/admin/users/views.py:70
+msgid "Unable to update user."
+msgstr ""
+
+#: dashboards/admin/users/views.py:104
+msgid "Unable to retrieve user roles."
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_create.html:17
+msgid "From here you can create a new user and assign them to a project."
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_update.html:7
+#: dashboards/admin/users/templates/users/_update.html:22
+#: dashboards/admin/users/templates/users/update.html:7
+msgid "Update User"
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_update.html:17
+msgid ""
+"From here you can edit the user's details, including their default project."
+msgstr ""
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:3
+#: dashboards/project/volumes/templates/volumes/detail.html:3
+msgid "Volume Details"
+msgstr ""
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:6
+#: dashboards/project/volumes/templates/volumes/detail.html:6
+msgid "Volume Detail"
+msgstr ""
+
+#: dashboards/project/dashboard.py:24
+msgid "Manage Compute"
+msgstr ""
+
+#: dashboards/project/dashboard.py:35
+msgid "Object Store"
+msgstr ""
+
+#: dashboards/project/access_and_security/panel.py:26
+#: dashboards/project/instances/workflows.py:348
+msgid "Access & Security"
+msgstr ""
+
+#: dashboards/project/access_and_security/views.py:51
+msgid "Unable to retrieve keypair list."
+msgstr ""
+
+#: dashboards/project/access_and_security/views.py:60
+#: dashboards/project/access_and_security/security_groups/views.py:74
+msgid "Unable to retrieve security groups."
+msgstr ""
+
+#: dashboards/project/access_and_security/views.py:69
+#: dashboards/project/access_and_security/floating_ips/workflows.py:49
+msgid "Unable to retrieve floating IP addresses."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:32
+msgid "Pool"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:43
+#, python-format
+msgid "Allocated Floating IP %(ip)s."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:47
+msgid "Unable to allocate Floating IP."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:37
+msgid "Allocate IP To Project"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:47
+msgid "Release"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:48
+msgid "Released"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:49
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:22
+msgid "Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:6
+#: dashboards/project/instances/tables.py:219
+msgid "Associate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:76
+msgid "Disassociate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:90
+#, python-format
+msgid "Successfully disassociated Floating IP: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:94
+msgid "Unable to disassociate floating IP."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:114
+#: dashboards/project/access_and_security/floating_ips/workflows.py:36
+#: dashboards/project/instances/tables.py:69
+#: dashboards/project/instances/tables.py:89
+#: dashboards/project/instances/tables.py:106
+#: dashboards/project/instances/tables.py:135
+#: dashboards/project/volumes/tables.py:206
+msgid "Instance"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:117
+msgid "Floating IP Pool"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:65
+msgid "Unable to retrieve floating IP pools."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:68
+msgid "No floating IP pools available."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:40
+msgid "Select the IP address you wish to associate with the selected instance."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:53
+msgid "Select an IP address"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:55
+msgid "No IP addresses available"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:76
+#: dashboards/project/volumes/forms.py:160
+msgid "Select an instance"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:78
+#: dashboards/project/volumes/forms.py:162
+msgid "No instances available"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:97
+msgid "Manage Floating IP Associations"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:98
+msgid "Associate"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:99
+#, python-format
+msgid "IP address %s associated."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:100
+#, python-format
+msgid "Unable to associate IP address %s."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:38
+#: dashboards/project/access_and_security/keypairs/forms.py:49
+#: dashboards/project/access_and_security/keypairs/tables.py:52
+msgid "Keypair Name"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:40
+msgid ""
+"Keypair names may only contain letters, numbers, underscores and hyphens."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:51
+msgid "Public Key"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:60
+#, python-format
+msgid "Successfully imported public key: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:65
+msgid "Unable to import keypair."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:30
+#: dashboards/project/instances/tables.py:295
+#: dashboards/project/instances/workflows.py:335
+msgid "Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:31
+#: dashboards/project/access_and_security/keypairs/tables.py:60
+msgid "Keypairs"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:39
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html:6
+msgid "Import Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:46
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html:6
+msgid "Create Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:53
+msgid "Fingerprint"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/views.py:74
+#, python-format
+msgid "Unable to create keypair: %(exc)s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:46
+#, python-format
+msgid "Successfully created security group: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:52
+msgid "Unable to create security group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:57
+#: dashboards/project/access_and_security/security_groups/tables.py:93
+msgid "IP Protocol"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:61
+msgid "The protocol which this rule should be applied to."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:65
+#: dashboards/project/access_and_security/security_groups/forms.py:71
+#: dashboards/project/access_and_security/security_groups/tables.py:95
+msgid "From Port"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:66
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP type in the range (-1: 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:72
+#: dashboards/project/images_and_snapshots/images/tables.py:115
+msgid "Type"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:74
+#: dashboards/project/access_and_security/security_groups/forms.py:80
+#: dashboards/project/access_and_security/security_groups/tables.py:96
+msgid "To Port"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:75
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP code in the range (-1: 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:81
+msgid "Code"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:84
+msgid "Source Group"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:86
+msgid ""
+"To specify an allowed IP range, select CIDR. To allow access from all "
+"members of another security group select Source Group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:94
+msgid "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:121
+msgid "The ICMP type is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:124
+msgid "The ICMP code is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:127
+msgid "The ICMP type not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:130
+msgid "The ICMP code not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:134
+msgid "The \"from\" port number is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:137
+msgid "The \"to\" port number is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:140
+msgid ""
+"The \"to\" port number must be greater than or equal to the \"from\" port "
+"number."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:146
+msgid "Either CIDR or Source Group may be specified, but not both."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:168
+#, python-format
+msgid "Successfully added rule: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:173
+msgid "Unable to add rule to security group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:31
+msgid "Security Group"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:32
+#: dashboards/project/access_and_security/security_groups/tables.py:66
+#: dashboards/project/instances/workflows.py:340
+#: dashboards/project/instances/templates/instances/_detail_overview.html:49
+msgid "Security Groups"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:45
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html:6
+msgid "Create Security Group"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:52
+msgid "Edit Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:72
+msgid "Rule"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:73
+msgid "Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:97
+msgid "Source"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:107
+msgid "Security Group Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/views.py:60
+msgid "Unable to retrieve security group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/views.py:80
+#, python-format
+msgid "%s (current)"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/index.html:6
+msgid "Access &amp; Security"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:8
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html:3
+msgid "Allocate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:18
+msgid "Allocate a floating IP from a given floating ip pool."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:20
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:19
+#, fuzzy
+msgid "Project Quotas"
+msgstr "Projekty"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:31
+msgid "Allocate IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:17
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:17
+msgid ""
+"Keypairs are ssh credentials which are injected into images when they are "
+"launched. Creating a new key pair registers the public key and downloads the "
+"private key (a .pem file)."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:18
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:18
+msgid "Protect and use the key as you would any normal ssh private key."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:6
+msgid "Download Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:11
+#, python-format
+msgid ""
+"The keypair &quot;%(keypair_name)s&quot; should download automatically. If "
+"not use the link below."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:15
+#, python-format
+msgid "Download keypair &quot;%(keypair_name)s&quot;"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:18
+msgid "From here you can create a new security group"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:9
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html:6
+msgid "Edit Security Group Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:12
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:19
+msgid "Add Rule"
+msgstr ""
+
+#: dashboards/project/containers/browsers.py:26
+msgid "Swift"
+msgstr ""
+
+#: dashboards/project/containers/browsers.py:29
+#: dashboards/project/containers/tables.py:40
+msgid "Container"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:39
+msgid "Slash is not an allowed character."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:49
+#: dashboards/project/containers/tables.py:121
+msgid "Container Name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:57
+msgid "Container created successfully."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:68
+msgid "Folder created successfully."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:71
+msgid "Unable to create container."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:79
+#: dashboards/project/containers/tables.py:253
+msgid "Object Name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:81
+msgid "File"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:95
+msgid "Object was successfully uploaded."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:98
+msgid "Unable to upload object."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:102
+msgid "Destination container"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:106
+msgid "Destination object name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:137
+#: dashboards/project/containers/forms.py:163
+msgid "Unable to copy object."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:153
+#, python-format
+msgid "Copied \"%(orig)s\" to \"%(dest)s\" as \"%(new)s\"."
+msgstr ""
+
+#: dashboards/project/containers/panel.py:29
+#: dashboards/project/containers/tables.py:41
+#: dashboards/project/containers/tables.py:128
+#: dashboards/project/containers/templates/containers/index.html:7
+msgid "Containers"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:62
+#: dashboards/project/containers/templates/containers/_create.html:7
+#: dashboards/project/containers/templates/containers/_create.html:22
+#: dashboards/project/containers/templates/containers/create.html:6
+msgid "Create Container"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:69
+msgid "View Container"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:81
+#: dashboards/project/containers/templates/containers/_upload.html:23
+#: dashboards/project/containers/templates/containers/upload.html:3
+msgid "Upload Object"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:137
+#: dashboards/project/containers/tables.py:156
+msgid "Object"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:138
+#: dashboards/project/containers/tables.py:157
+#: dashboards/project/containers/tables.py:263
+#, fuzzy
+msgid "Objects"
+msgstr "Projekty"
+
+#: dashboards/project/containers/tables.py:149
+msgid "Folder"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:150
+msgid "Folders"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:163
+msgid "Copy"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:176
+msgid "Download"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:232
+msgid "Create Folder"
+msgstr ""
+
+#: dashboards/project/containers/views.py:53
+msgid "Unable to retrieve container list."
+msgstr ""
+
+#: dashboards/project/containers/views.py:82
+msgid "Unable to retrieve object list."
+msgstr ""
+
+#: dashboards/project/containers/views.py:166
+msgid "Unable to retrieve object."
+msgstr ""
+
+#: dashboards/project/containers/views.py:200
+msgid "Unable to list containers."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_copy.html:7
+#: dashboards/project/containers/templates/containers/_copy.html:22
+#: dashboards/project/containers/templates/containers/copy.html:3
+#: dashboards/project/containers/templates/containers/copy.html:6
+msgid "Copy Object"
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_copy.html:17
+msgid ""
+"Make a new copy of an existing object to store in this or another container. "
+"You may also specify a path at which the new copy should live inside of the "
+"selected container."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_create.html:17
+msgid ""
+"A container is a storage compartment for your data and provides a way for "
+"you to organize your data. You can think of a container as a folder in "
+"Windows &reg; or a directory in UNIX &reg;. The primary difference between a "
+"container and these other file system concepts is that containers cannot be "
+"nested. You can, however, create an unlimited number of containers within "
+"your account. Data must be stored in a container so you must have at least "
+"one container defined in your account prior to uploading data."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:8
+msgid "Upload Object To Container"
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:18
+msgid ""
+"An object is the basic storage entity and any optional metadata that "
+"represents the files you store in the OpenStack Object Storage system. When "
+"you upload data to OpenStack Object Storage, the data is stored as-is (no "
+"compression or encryption) and consists of a location (container), the "
+"object's name, and any metadata consisting of key/value pairs."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/upload.html:6
+msgid "Upload Objects"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/panel.py:26
+msgid "Images & Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:63
+msgid "Unable to retrieve images."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:74
+msgid "Unable to retrieve snapshots."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:82
+#: dashboards/project/volumes/forms.py:65
+msgid "Unable to retrieve volume snapshots."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:42
+msgid "Image Location"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:43
+msgid "An external (HTTP) URL to load the image from."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:46
+#: dashboards/project/images_and_snapshots/images/forms.py:130
+#: dashboards/project/images_and_snapshots/images/tables.py:126
+msgid "Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:50
+msgid "AKI - Amazon Kernel Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:53
+msgid "AMI - Amazon Machine Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:56
+msgid "ARI - Amazon Ramdisk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:59
+msgid "ISO - Optical Disk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:61
+msgid "QCOW2 - QEMU Emulator"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:68
+msgid "Minimum Disk (GB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:69
+#: dashboards/project/images_and_snapshots/images/forms.py:76
+msgid ""
+"The minimum disk size required to boot the image. If unspecified, this value "
+"defaults to 0 (no minimum)."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:75
+msgid "Minimum Ram (MB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:82
+#: dashboards/project/images_and_snapshots/images/forms.py:134
+#: dashboards/project/images_and_snapshots/images/tables.py:123
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:15
+msgid "Public"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:106
+#, python-format
+msgid "Your image %s has been queued for creation."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:110
+msgid "Unable to create new image."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:116
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:48
+msgid "Kernel ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:121
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:52
+msgid "Ramdisk ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:126
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:44
+msgid "Architecture"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:138
+#, python-format
+msgid "Unable to update image \"%s\"."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:162
+msgid "Image was successfully updated."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tables.py:34
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:33
+#: dashboards/project/instances/workflows.py:455
+msgid "Launch"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tables.py:46
+#: dashboards/project/images_and_snapshots/images/tables.py:82
+#: dashboards/project/instances/workflows.py:168
+#: dashboards/project/instances/workflows.py:173
+msgid "Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tables.py:61
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:31
+msgid "Create Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tabs.py:38
+msgid "Unable to retrieve image details."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/views.py:61
+msgid "Unable to retrieve image."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:37
+msgid "Instance ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:40
+#: dashboards/project/volumes/forms.py:193
+msgid "Snapshot Name"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:50
+#, python-format
+msgid "Snapshot \"%(name)s\" created for instance \"%(inst)s\""
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:56
+msgid "Unable to create snapshot."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:48
+#: dashboards/project/instances/workflows.py:107
+#: dashboards/project/instances/workflows.py:169
+msgid "Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:49
+msgid "Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:55
+msgid "Instance Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/views.py:53
+msgid "Unable to retrieve instance."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:6
+msgid "Images &amp; Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:6
+msgid "Create An Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:18
+msgid "Specify an image to upload to the Image Service."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:21
+msgid ""
+"Currently only images available via an HTTP URL are supported. The image "
+"location must be accessible to the Image Service. Compressed image binaries "
+"are supported (.zip and .tar.gz.)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:24
+msgid "Please note: "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:25
+msgid ""
+"The Image Location field MUST be a valid and direct URL to the image binary. "
+"URLs that redirect or serve error pages will result in unusable images."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:3
+msgid "Image Overview"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:6
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:7
+#: dashboards/project/instances/templates/instances/_detail_overview.html:6
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:6
+msgid "Info"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:17
+msgid "Checksum"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:19
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:39
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:28
+msgid "Created"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:21
+msgid "Updated"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:27
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:34
+#: dashboards/project/instances/templates/instances/_detail_overview.html:19
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:23
+msgid "Specs"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:32
+msgid "Container Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:34
+msgid "Disk Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:40
+msgid "Custom Properties"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:56
+msgid "Euca2ools state"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:64
+msgid "Image Type"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html:4
+msgid "Image Detail "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:8
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:3
+#: dashboards/project/instances/tables.py:179
+#: dashboards/project/volumes/tables.py:76
+msgid "Create Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:18
+msgid "Snapshots preserve the disk state of a running instance."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:20
+#: dashboards/project/instances/workflows.py:75
+#: dashboards/project/instances/workflows.py:110
+#: dashboards/project/instances/templates/instances/_detail_overview.html:93
+#: dashboards/project/volumes/tables.py:37
+#: dashboards/project/volumes/tables.py:182
+msgid "Volume"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:38
+#: dashboards/project/instances/templates/instances/_detail_overview.html:29
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:27
+msgid "GB"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:6
+msgid "Create a Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:3
+msgid "Volume Snapshot Details"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:6
+msgid "Volume Snapshot Detail"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:34
+#: dashboards/project/instances/workflows.py:76
+msgid "Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:35
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:85
+msgid "Volume Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:43
+#: dashboards/project/volumes/tables.py:59
+#: dashboards/project/volumes/templates/volumes/_create.html:8
+#: dashboards/project/volumes/templates/volumes/_create.html:55
+msgid "Create Volume"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:80
+#: dashboards/project/volumes/forms.py:26
+msgid "Volume Name"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:41
+msgid "Unable to retrieve snapshot details."
+msgstr ""
+
+#: dashboards/project/instances/forms.py:45
+#, python-format
+msgid "Instance \"%s\" updated."
+msgstr ""
+
+#: dashboards/project/instances/forms.py:50
+msgid "Unable to update instance."
+msgstr ""
+
+#: dashboards/project/instances/tables.py:67
+msgid "Terminate"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:68
+msgid "Scheduled termination of"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:87
+msgid "Reboot"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:88
+msgid "Rebooted"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:104
+msgid "Pause"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:104
+msgid "Unpause"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:105
+msgid "Paused"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:105
+msgid "Unpaused"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:133
+msgid "Suspend"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:133
+msgid "Resume"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:134
+msgid "Suspended"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:134
+msgid "Resumed"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:162
+#: dashboards/project/instances/workflows.py:454
+#: dashboards/project/instances/templates/instances/launch.html:3
+#: dashboards/project/instances/templates/instances/launch.html:6
+msgid "Launch Instance"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:169
+#: dashboards/project/instances/templates/instances/_update.html:7
+msgid "Edit Instance"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:189
+msgid "VNC Console"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:204
+msgid "View Log"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:252
+#, python-format
+msgid "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disk"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:259
+#: dashboards/project/instances/tables.py:266
+msgid "Not available"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:36
+msgid "Log"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:48
+#: dashboards/project/instances/views.py:106
+#, python-format
+msgid "Unable to get log for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:55
+msgid "VNC"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:70
+#: dashboards/project/instances/views.py:122
+#, python-format
+msgid "Unable to get VNC console for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/views.py:59
+msgid "Unable to retrieve instances."
+msgstr ""
+
+#: dashboards/project/instances/views.py:144
+msgid "Unable to retrieve instance details."
+msgstr ""
+
+#: dashboards/project/instances/views.py:179
+#, python-format
+msgid "Unable to retrieve details for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:53
+#, fuzzy
+msgid "Project & User"
+msgstr "Projekty"
+
+#: dashboards/project/instances/workflows.py:66
+msgid "Don't boot from a volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:67
+msgid "Boot from volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:68
+msgid "Boot from volume snapshot (creates a new volume)."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:72
+#: dashboards/project/instances/workflows.py:90
+msgid "Volume Options"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:78
+#: dashboards/project/volumes/forms.py:126
+msgid "Device Name"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:81
+msgid "Volume mount point (e.g. 'vda' mounts at '/dev/vda')."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:83
+msgid "Delete on Terminate"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:86
+msgid "Delete volume on instance terminate"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:100
+#, python-format
+msgid "Please choose a volume, or select %s."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:117
+msgid "Select Volume"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:125
+msgid "Unable to retrieve list of volumes."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:129
+msgid "Select Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:138
+msgid "Unable to retrieve list of volume snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:171
+msgid "Instance Source"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:174
+msgid "Instance Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:178
+msgid "Size of image to launch."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:179
+msgid "Instance Count"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:182
+msgid "Number of instances to launch."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:185
+msgid "Details"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:198
+msgid ""
+"There are no image sources available; you must first create an image before "
+"attempting to launch an instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:203
+msgid "Please select an option for the instance source."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:212
+msgid ""
+"Launching multiple instances is only supported for images and instance "
+"snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:229
+msgid "Unable to retrieve public images."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:244
+msgid "Unable to retrieve images for the current project."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:267
+msgid "Select Image"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:269
+msgid "No images available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:278
+msgid "Select Instance Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:280
+msgid "No snapshots available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:291
+msgid "Unable to retrieve instance flavors."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:304 usage/base.py:114
+msgid "Unable to retrieve quota information."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:337
+msgid "Which keypair to use for authentication."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:344
+msgid "Launch instance in these security groups."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:349
+msgid ""
+"Control access to your instance via keypairs, security groups, and other "
+"mechanisms."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:359
+msgid "Unable to retrieve keypairs."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:361
+msgid "Select a keypair"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:363
+msgid "No keypairs available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:372
+msgid "Unable to retrieve list of security groups"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:392
+msgid "Customization Script"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:394
+msgid ""
+"A script or set of commands to be executed after the instance has been built "
+"(max 16kb)."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:401
+msgid "Post-Creation"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:415
+msgid "Launch instance withthese networks"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:419
+msgid "Networking"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:421
+msgid "Select networks for your instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:433
+msgid "Unable to retrieve networks."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:456
+#, python-format
+msgid "Launched %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:457
+#, python-format
+msgid "Unable to launch %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:470
+#, python-format
+msgid "%s instances"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:473
+msgid "instance"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:4
+msgid "Instance Console Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:7
+msgid "Log Length"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:9
+msgid "Go"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:11
+msgid "View Full Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:3
+msgid "Instance Overview"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:27
+msgid "VCPU"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:28
+#: usage/tables.py:20
+msgid "Disk"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:34
+msgid "IP Addresses"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:59
+msgid "No rules defined."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:68
+msgid "Meta"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:71
+msgid "Key Name"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:84
+msgid "Volumes Attached"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:88
+#: dashboards/project/volumes/tables.py:167
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:38
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:45
+msgid "Attached To"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:90
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:42
+msgid "on"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:94
+msgid "No volumes attached."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:3
+msgid "Instance VNC Console"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid ""
+"If VNC console is not responding to keyboard input: click the grey status "
+"bar below."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid "Click here to show only VNC"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:8
+msgid "VNC console is currently unavailabe. Please try again later."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:9
+msgid "Reload"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:2
+msgid ""
+"You can customize your instance after it's launched using the options "
+"available here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:3
+msgid ""
+"The \"Customization Script\" field is analogous to \"User Data\" in other "
+"systems."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:3
+msgid "Specify the details for launching an instance."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:4
+msgid ""
+"The chart below shows the resources used by this project in relation to the "
+"project's quotas."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:6
+msgid "Flavor Details"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+msgid "Total Disk"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "MB"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:21
+msgid "Number of Instances"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:29
+msgid "Number of VCPUs"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "Total RAM"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_volumes_help.html:3
+msgid ""
+"An instance can be launched with varying types of attached storage. You may "
+"select from those options here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_update.html:17
+msgid "You may update the editable properties of your instance here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/detail.html:3
+msgid "Instance Detail"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/update.html:3
+#: dashboards/project/instances/templates/instances/update.html:6
+msgid "Update Instance"
+msgstr ""
+
+#: dashboards/project/networks/tables.py:81
+msgid "Add Subnet"
+msgstr ""
+
+#: dashboards/project/networks/views.py:86
+msgid "Unable to retrieve network details."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:37
+msgid "Network Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:42
+msgid ""
+"From here you can create a new network.\n"
+"In addition a subnet associated with the network can be created in the next "
+"panel."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:56
+msgid "Subnet Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:61
+#: dashboards/project/networks/subnets/forms.py:48
+msgid "Network address in CIDR format (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:67
+msgid "Gateway IP (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:70
+#: dashboards/project/networks/subnets/forms.py:57
+#: dashboards/project/networks/subnets/forms.py:107
+msgid "IP address of Gateway (e.g. 192.168.0.1)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:77
+msgid ""
+"You can create a subnet associated with the new network, in which case "
+"\"Network Address\" must be specified. If you wish to create a network "
+"WITHOUT a subnet, uncheck the \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:89
+msgid "Specify \"Network Address\" or clear \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:94
+#: dashboards/project/networks/subnets/forms.py:70
+msgid "Network Address and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:98
+#: dashboards/project/networks/subnets/forms.py:74
+#: dashboards/project/networks/subnets/forms.py:119
+msgid "Gateway IP and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:112
+msgid "Create"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:113
+#, python-format
+msgid "Created network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:114
+#, python-format
+msgid "Unable to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:130
+#, python-format
+msgid "Network \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:133
+#, python-format
+msgid "Failed to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:152
+#, python-format
+msgid "Subnet \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:155
+#, python-format
+msgid "Failed to create subnet \"%(sub)s\" for network \"%(net)s\"."
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Attached"
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Detached"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:85
+#, python-format
+msgid "Subnet %s was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:90
+#, python-format
+msgid "Failed to create subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:131
+#, python-format
+msgid "Subnet %s was successfully updated."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:136
+#, python-format
+msgid "Failed to update subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/tabs.py:42
+msgid "Unable to retrieve subnet details."
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/_detail_overview.html:3
+msgid "Network Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/detail.html:6
+msgid "Network Detail: "
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:3
+msgid "Port Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:17
+msgid "Fixed IP"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:21
+msgid "IP address:"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:22
+msgid "Subnet ID"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:28
+msgid "Mac Address"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/detail.html:3
+#: dashboards/project/networks/templates/networks/ports/detail.html:6
+msgid "Port Detail"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:3
+msgid "Subnet Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:21
+msgid "IP allocation pool"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:24
+msgid "Start"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:25
+msgid " - End"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/detail.html:3
+#: dashboards/project/networks/templates/networks/subnets/detail.html:6
+msgid "Subnet Detail"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:29
+msgid "Size (GB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:30
+msgid "Use snapshot as a source"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:49
+#, python-format
+msgid "Volume size must be equal to or greater than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:54
+msgid "Unable to load the specified snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:59
+msgid "Choose a snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:83
+#, python-format
+msgid "The volume size cannot be less than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:92
+#, python-format
+msgid ""
+"A volume of %(req)iGB cannot be created as you only have %(avail)iGB of your "
+"quota available."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:99
+msgid "You are already using all of your available volumes."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:115
+msgid "Unable to create volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:123
+msgid "Attach to Instance"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:124
+msgid "Select an instance to attach to."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:168
+msgid "Unknown instance (None)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:179
+#, python-format
+msgid "Attaching volume %(vol)s to instance %(inst)s on %(dev)s."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:188
+msgid "Unable to attach volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:212
+#, python-format
+msgid "Creating volume snapshot \"%s\""
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:218
+msgid "Unable to create volume snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:46
+#, python-format
+msgid "Unable to delete volume \"%s\". One or more snapshots depend on it."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:66
+msgid "Edit Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:93
+#, python-format
+msgid "%sGB"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:106
+#: dashboards/project/volumes/views.py:149
+msgid "Unable to retrieve attachment information."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:123
+#, python-format
+msgid "Attached to %(instance)s on %(dev)s"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:180
+msgid "Detach"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:181
+msgid "Detaching"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:216
+#, python-format
+msgid "%(dev)s on instance %(instance_name)s"
+msgstr ""
+
+#: dashboards/project/volumes/tabs.py:42
+msgid "Unable to retrieve volume details."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:50
+msgid "Unable to retrieve volume list."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:58
+msgid "Unable to retrieve volume/instance attachment information"
+msgstr ""
+
+#: dashboards/project/volumes/views.py:130
+#: dashboards/project/volumes/views.py:140
+msgid "Unable to retrieve volume information."
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:9
+#: dashboards/project/volumes/templates/volumes/attach.html:6
+msgid "Manage Volume Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:13
+msgid "Attach To Instance"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:22
+msgid "Attach Volume"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:20
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:18
+msgid "Volumes are block devices that can be attached to instances."
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:22
+msgid "Volume Quotas"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:25
+msgid "Total Gigabytes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:34
+msgid "Number of Volumes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:8
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:23
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:3
+msgid "Create Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:3
+msgid "Volume Overview"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:34
+msgid "Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:46
+msgid "Not attached"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/create.html:6
+msgid "Create a Volume"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:6
+msgid "Create a Volume Snapshot"
+msgstr ""
+
+#: dashboards/settings/dashboard.py:24 templates/_header.html:4
+msgid "Settings"
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:36 dashboards/settings/project/forms.py:36
+msgid "Select a Project"
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:46
+msgid "Unable to retrieve tenant list."
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:88
+msgid "Unable to fetch EC2 credentials."
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:101
+#, python-format
+msgid "Error writing zipfile: %(exc)s"
+msgstr ""
+
+#: dashboards/settings/ec2/panel.py:25
+msgid "EC2 Credentials"
+msgstr ""
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:8
+#: dashboards/settings/ec2/templates/ec2/download_form.html:23
+#: dashboards/settings/ec2/templates/ec2/index.html:3
+#: dashboards/settings/ec2/templates/ec2/index.html:6
+msgid "Download EC2 Credentials"
+msgstr ""
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:18
+msgid ""
+"Clicking \"Download EC2 Credentials\" will download a zip file which "
+"includes an rc file with your access/secret keys, as well as your x509 "
+"private key and certificate."
+msgstr ""
+
+#: dashboards/settings/project/forms.py:71
+#, python-format
+msgid "Error Downloading RC File: %s"
+msgstr ""
+
+#: dashboards/settings/project/panel.py:25
+#: dashboards/settings/project/templates/project/_openrc.html:8
+#: dashboards/settings/project/templates/project/settings.html:3
+#: dashboards/settings/project/templates/project/settings.html:6
+msgid "OpenStack API"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:27
+msgid "Service Name"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:29
+msgid "Service Endpoint"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:33
+msgid "API Endpoints"
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:15
+msgid "Download OpenStack RC File"
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:25
+msgid ""
+"Download the RC file for the selected project, then type \"source openrc\" "
+"in the terminal to configure your environment to communicate with OpenStack."
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:30
+msgid "Download RC File"
+msgstr ""
+
+#: dashboards/settings/user/forms.py:57
+msgid "Settings saved."
+msgstr ""
+
+#: dashboards/settings/user/panel.py:25
+#: dashboards/settings/user/templates/user/_settings.html:8
+#: dashboards/settings/user/templates/user/settings.html:3
+#: dashboards/settings/user/templates/user/settings.html:6
+msgid "User Settings"
+msgstr ""
+
+#: dashboards/settings/user/templates/user/_settings.html:18
+msgid "From here you can modify dashboard settings for your user."
+msgstr ""
+
#: templates/403.html:4 templates/403.html.py:9
msgid "Forbidden"
msgstr "Zakázáno"
@@ -83,10 +3247,6 @@ msgstr "Zakázáno"
msgid "Home"
msgstr "Domů"
-#: templates/403.html:24 templates/404.html:23 templates/500.html:23
-msgid "Projects"
-msgstr "Projekty"
-
#: templates/404.html:4
msgid "Page Not Found"
msgstr "Stránka nenalezena"
@@ -110,3 +3270,47 @@ msgid ""
msgstr ""
"Došlo k neočekávané chybě při zpracování vašeho požadavku. Prosím, zkuste "
"svůj požadavek znovu."
+
+#: templates/_header.html:3
+msgid "Logged in as"
+msgstr ""
+
+#: templates/_header.html:6
+msgid "Help"
+msgstr ""
+
+#: templates/_header.html:8
+msgid "Sign Out"
+msgstr ""
+
+#: test/settings.py:50
+msgid "Password must be between 8 and 18 characters."
+msgstr ""
+
+#: usage/base.py:97
+msgid "Unable to retrieve usage information."
+msgstr ""
+
+#: usage/base.py:100
+msgid "You are viewing data for the future, which may or may not exist."
+msgstr ""
+
+#: usage/tables.py:11
+msgid "Download CSV Summary"
+msgstr ""
+
+#: usage/tables.py:25
+msgid "VCPU Hours"
+msgstr ""
+
+#: usage/tables.py:32
+msgid "Disk GB Hours"
+msgstr ""
+
+#: usage/tables.py:40 usage/tables.py:68
+msgid "Usage Summary"
+msgstr ""
+
+#: usage/tables.py:60
+msgid "Uptime"
+msgstr ""
diff --git a/openstack_dashboard/locale/en/LC_MESSAGES/django.mo b/openstack_dashboard/locale/en/LC_MESSAGES/django.mo
index 5e93d01ae..04d5aec96 100644
--- a/openstack_dashboard/locale/en/LC_MESSAGES/django.mo
+++ b/openstack_dashboard/locale/en/LC_MESSAGES/django.mo
Binary files differ
diff --git a/openstack_dashboard/locale/en/LC_MESSAGES/django.po b/openstack_dashboard/locale/en/LC_MESSAGES/django.po
index 7095b0132..2f00dcb06 100644
--- a/openstack_dashboard/locale/en/LC_MESSAGES/django.po
+++ b/openstack_dashboard/locale/en/LC_MESSAGES/django.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Horizon\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-09-18 22:18+0000\n"
+"POT-Creation-Date: 2012-10-05 19:30+0000\n"
"PO-Revision-Date: 2012-08-14 08:40+0000\n"
"Last-Translator: Gabriel Hurley <gabriel@strikeawe.com>\n"
"Language-Team: English (http://www.transifex.com/projects/p/openstack/"
@@ -20,63 +20,3275 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: settings.py:141
+#: settings.py:142
msgid "Bulgarian (Bulgaria)"
msgstr ""
-#: settings.py:142
+#: settings.py:143
msgid "Czech"
msgstr ""
-#: settings.py:143
+#: settings.py:144
msgid "English"
msgstr "English"
-#: settings.py:144
+#: settings.py:145
msgid "Spanish"
msgstr "Spanish"
-#: settings.py:145
+#: settings.py:146
msgid "French"
msgstr "French"
-#: settings.py:146
+#: settings.py:147
msgid "Italiano"
msgstr "Italiano"
-#: settings.py:147
+#: settings.py:148
msgid "Japanese"
msgstr "Japanese"
-#: settings.py:148
+#: settings.py:149
msgid "Korean (Korea)"
msgstr ""
-#: settings.py:149
+#: settings.py:150
msgid "Dutch (Netherlands)"
msgstr ""
-#: settings.py:150
+#: settings.py:151
msgid "Polish"
msgstr "Polish"
-#: settings.py:151
+#: settings.py:152
msgid "Portuguese"
msgstr "Portuguese"
-#: settings.py:152
+#: settings.py:153
#, fuzzy
msgid "Portuguese (Brazil)"
msgstr "Portuguese"
-#: settings.py:153
+#: settings.py:154
msgid "Simplified Chinese"
msgstr "Simplified Chinese"
-#: settings.py:154
+#: settings.py:155
msgid "Traditional Chinese"
msgstr "Traditional Chinese"
+#: api/keystone.py:56
+#, python-format
+msgid "%(type)s (%(backend)s backend)"
+msgstr "%(type)s (%(backend)s backend)"
+
+#: api/nova.py:191
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(group)s"
+msgstr "ALLOW %(from)s:%(to)s from %(group)s"
+
+#: api/nova.py:196
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(cidr)s"
+msgstr "ALLOW %(from)s:%(to)s from %(cidr)s"
+
+#: api/nova.py:532
+msgid "Unknown instance"
+msgstr "Unknown Instance"
+
+#: api/swift.py:217
+msgid "Unicode is not currently supported for object copy."
+msgstr "Unicode is not currently supported for object copy."
+
+#: dashboards/admin/dashboard.py:24
+msgid "System Panel"
+msgstr "System Panel"
+
+#: dashboards/admin/dashboard.py:30
+msgid "Admin"
+msgstr "Admin"
+
+#: dashboards/admin/flavors/forms.py:36 dashboards/admin/networks/forms.py:34
+#: dashboards/admin/networks/forms.py:69
+#: dashboards/admin/networks/ports/forms.py:40
+#: dashboards/admin/networks/ports/forms.py:72
+#: dashboards/admin/networks/ports/tables.py:73
+#: dashboards/admin/networks/subnets/tables.py:70
+#: dashboards/admin/projects/tables.py:87
+#: dashboards/admin/projects/workflows.py:71
+#: dashboards/admin/services/tables.py:38
+#: dashboards/admin/volumes/tables.py:10
+#: dashboards/project/access_and_security/security_groups/forms.py:36
+#: dashboards/project/access_and_security/security_groups/tables.py:58
+#: dashboards/project/images_and_snapshots/images/forms.py:40
+#: dashboards/project/images_and_snapshots/images/forms.py:115
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:9
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:10
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:77
+#: dashboards/project/instances/templates/instances/_detail_overview.html:9
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:9
+#: dashboards/project/networks/forms.py:37
+#: dashboards/project/networks/tables.py:94
+#: dashboards/project/networks/ports/tables.py:40
+#: dashboards/project/networks/subnets/forms.py:43
+#: dashboards/project/networks/subnets/forms.py:102
+#: dashboards/project/networks/subnets/tables.py:82
+#: dashboards/project/networks/templates/networks/_detail_overview.html:7
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:9
+#: dashboards/project/volumes/tables.py:144
+#: dashboards/project/volumes/tables.py:164
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:9
+msgid "Name"
+msgstr "Name"
+
+#: dashboards/admin/flavors/forms.py:37 dashboards/admin/flavors/tables.py:41
+#: dashboards/admin/projects/workflows.py:39
+#: dashboards/project/instances/templates/instances/_detail_overview.html:26
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:10
+#: usage/tables.py:19
+msgid "VCPUs"
+msgstr "VCPUs"
+
+#: dashboards/admin/flavors/forms.py:38
+msgid "RAM MB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:39
+msgid "Root Disk GB"
+msgstr "Root Disk GB"
+
+#: dashboards/admin/flavors/forms.py:40
+msgid "Ephemeral Disk GB"
+msgstr "Ephemeral Disk GB"
+
+#: dashboards/admin/flavors/forms.py:50
+msgid "Unable to get unique ID for new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:67
+#, python-format
+msgid "Created flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:71
+msgid "Unable to create flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:92
+#, python-format
+msgid "Updated flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:96
+msgid "Unable to update flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/panel.py:29 dashboards/admin/flavors/tables.py:15
+#: dashboards/admin/flavors/tables.py:52
+#: dashboards/admin/flavors/templates/flavors/index.html:3
+#: dashboards/admin/flavors/templates/flavors/index.html:6
+msgid "Flavors"
+msgstr "Flavors"
+
+#: dashboards/admin/flavors/tables.py:14
+#: dashboards/project/instances/workflows.py:177
+#: dashboards/project/instances/templates/instances/_detail_overview.html:22
+msgid "Flavor"
+msgstr "Flavor"
+
+#: dashboards/admin/flavors/tables.py:23
+#: dashboards/admin/flavors/templates/flavors/_create.html:8
+#: dashboards/admin/flavors/templates/flavors/_create.html:23
+#: dashboards/admin/flavors/templates/flavors/create.html:3
+#: dashboards/admin/flavors/templates/flavors/create.html:6
+msgid "Create Flavor"
+msgstr "Create Flavor"
+
+#: dashboards/admin/flavors/tables.py:30
+#: dashboards/admin/flavors/templates/flavors/_edit.html:8
+#: dashboards/admin/flavors/templates/flavors/edit.html:3
+#: dashboards/admin/flavors/templates/flavors/edit.html:6
+msgid "Edit Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:36
+#, python-format
+msgid "%sMB"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:40
+msgid "Flavor Name"
+msgstr "Flavor Name"
+
+#: dashboards/admin/flavors/tables.py:43
+#: dashboards/project/instances/templates/instances/_detail_overview.html:24
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: usage/tables.py:22
+msgid "RAM"
+msgstr "RAM"
+
+#: dashboards/admin/flavors/tables.py:45
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+msgid "Root Disk"
+msgstr "Root Disk"
+
+#: dashboards/admin/flavors/tables.py:47
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+msgid "Ephemeral Disk"
+msgstr "Ephemeral Disk"
+
+#: dashboards/admin/flavors/views.py:49
+msgid "Unable to retrieve flavor list."
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:76
+msgid "Unable to retrieve flavor data."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:17
+#: dashboards/admin/flavors/templates/flavors/_edit.html:17
+#: dashboards/admin/images/templates/images/_update.html:17
+#: dashboards/admin/networks/templates/networks/_create.html:17
+#: dashboards/admin/networks/templates/networks/ports/_create.html:17
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:17
+#: dashboards/admin/projects/tables.py:89
+#: dashboards/admin/projects/workflows.py:74
+#: dashboards/admin/projects/templates/projects/_add_user.html:17
+#: dashboards/admin/projects/templates/projects/_create.html:17
+#: dashboards/admin/projects/templates/projects/_create_user.html:17
+#: dashboards/admin/projects/templates/projects/_quotas.html:16
+#: dashboards/admin/projects/templates/projects/_update.html:17
+#: dashboards/admin/users/templates/users/_create.html:16
+#: dashboards/admin/users/templates/users/_update.html:16
+#: dashboards/project/access_and_security/security_groups/forms.py:38
+#: dashboards/project/access_and_security/security_groups/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:17
+#: dashboards/project/containers/templates/containers/_copy.html:16
+#: dashboards/project/containers/templates/containers/_create.html:16
+#: dashboards/project/containers/templates/containers/_upload.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/_create.html:16
+#: dashboards/project/networks/templates/networks/subnets/_create.html:17
+#: dashboards/project/volumes/forms.py:28
+#: dashboards/project/volumes/forms.py:195
+#: dashboards/project/volumes/tables.py:147
+#: dashboards/project/volumes/templates/volumes/_create.html:18
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:17
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:14
+msgid "Description"
+msgstr "Description"
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:18
+msgid "From here you can define the sizing of a new flavor."
+msgstr "From here you can define the sizing of a new flavor."
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:24
+#: dashboards/admin/flavors/templates/flavors/_edit.html:25
+#: dashboards/admin/images/templates/images/_update.html:24
+#: dashboards/admin/networks/templates/networks/_create.html:24
+#: dashboards/admin/networks/templates/networks/_update.html:23
+#: dashboards/admin/networks/templates/networks/ports/_create.html:24
+#: dashboards/admin/networks/templates/networks/ports/_update.html:28
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:24
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:32
+#: dashboards/admin/projects/templates/projects/_add_user.html:24
+#: dashboards/admin/projects/templates/projects/_create.html:24
+#: dashboards/admin/projects/templates/projects/_create_user.html:24
+#: dashboards/admin/projects/templates/projects/_quotas.html:23
+#: dashboards/admin/projects/templates/projects/_update.html:24
+#: dashboards/admin/users/templates/users/_create.html:23
+#: dashboards/admin/users/templates/users/_update.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:32
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:20
+#: dashboards/project/containers/templates/containers/_copy.html:23
+#: dashboards/project/containers/templates/containers/_create.html:23
+#: dashboards/project/containers/templates/containers/_upload.html:24
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:32
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:24
+#: dashboards/project/instances/templates/instances/_update.html:23
+#: dashboards/project/networks/templates/networks/_create.html:23
+#: dashboards/project/networks/templates/networks/_update.html:23
+#: dashboards/project/networks/templates/networks/subnets/_create.html:24
+#: dashboards/project/networks/templates/networks/subnets/_update.html:32
+#: dashboards/project/volumes/templates/volumes/_attach.html:24
+#: dashboards/project/volumes/templates/volumes/_create.html:56
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:24
+#: dashboards/settings/ec2/templates/ec2/download_form.html:24
+#: dashboards/settings/project/templates/project/_openrc.html:31
+#: dashboards/settings/user/templates/user/_settings.html:24
+msgid "Cancel"
+msgstr "Cancel"
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:18
+msgid "From here you can alter the sizing of the current flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:19
+msgid ""
+"Note: this will not affect the resources allocated to any existing instances "
+"using this flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:24
+#: dashboards/admin/projects/workflows.py:270
+#: dashboards/settings/user/templates/user/_settings.html:23
+msgid "Save"
+msgstr "Save"
+
+#: dashboards/admin/images/panel.py:29 dashboards/admin/images/tables.py:44
+#: dashboards/admin/images/templates/images/index.html:3
+#: dashboards/admin/images/templates/images/index.html:6
+#: dashboards/project/images_and_snapshots/images/tables.py:47
+#: dashboards/project/images_and_snapshots/images/tables.py:132
+msgid "Images"
+msgstr "Images"
+
+#: dashboards/admin/images/tables.py:40
+#: dashboards/project/images_and_snapshots/images/tables.py:113
+#: dashboards/project/instances/templates/instances/_detail_overview.html:74
+msgid "Image Name"
+msgstr "Image Name"
+
+#: dashboards/admin/images/views.py:55
+msgid "Unable to retrieve image list."
+msgstr "Unable to retrieve image list."
+
+#: dashboards/admin/images/templates/images/_update.html:8
+#: dashboards/admin/images/templates/images/_update.html:23
+#: dashboards/admin/images/templates/images/update.html:4
+#: dashboards/admin/images/templates/images/update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:22
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:6
+msgid "Update Image"
+msgstr "Update Image"
+
+#: dashboards/admin/images/templates/images/_update.html:18
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:17
+msgid "From here you can modify different properties of an image."
+msgstr "From here you can modify different properties of an image."
+
+#: dashboards/admin/instances/panel.py:29
+#: dashboards/admin/instances/tables.py:94
+#: dashboards/admin/instances/templates/instances/index.html:3
+#: dashboards/admin/projects/workflows.py:40
+#: dashboards/project/instances/panel.py:25
+#: dashboards/project/instances/tables.py:70
+#: dashboards/project/instances/tables.py:90
+#: dashboards/project/instances/tables.py:107
+#: dashboards/project/instances/tables.py:136
+#: dashboards/project/instances/tables.py:313
+#: dashboards/project/instances/templates/instances/index.html:3
+#: dashboards/project/instances/templates/instances/index.html:6
+msgid "Instances"
+msgstr "Instances"
+
+#: dashboards/admin/instances/tables.py:60 usage/tables.py:30
+msgid "Project Name"
+msgstr "Project Name"
+
+#: dashboards/admin/instances/tables.py:67
+#: dashboards/admin/services/tables.py:40
+msgid "Host"
+msgstr "Host"
+
+#: dashboards/admin/instances/tables.py:71
+#: dashboards/project/instances/tables.py:290
+#: dashboards/project/instances/workflows.py:176 usage/tables.py:57
+msgid "Instance Name"
+msgstr "Instance Name"
+
+#: dashboards/admin/instances/tables.py:72
+#: dashboards/project/access_and_security/floating_ips/tables.py:111
+#: dashboards/project/access_and_security/floating_ips/workflows.py:32
+#: dashboards/project/access_and_security/floating_ips/workflows.py:39
+#: dashboards/project/instances/tables.py:291
+msgid "IP Address"
+msgstr "IP Address"
+
+#: dashboards/admin/instances/tables.py:74
+#: dashboards/project/containers/tables.py:256
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:30
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:37
+#: dashboards/project/instances/tables.py:293
+#: dashboards/project/volumes/tables.py:150
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:26
+msgid "Size"
+msgstr "Size"
+
+#: dashboards/admin/instances/tables.py:79
+#: dashboards/admin/networks/tables.py:74
+#: dashboards/admin/networks/ports/tables.py:77
+#: dashboards/project/images_and_snapshots/images/tables.py:119
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:13
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:18
+#: dashboards/project/instances/tables.py:298
+#: dashboards/project/instances/templates/instances/_detail_overview.html:13
+#: dashboards/project/networks/tables.py:100
+#: dashboards/project/networks/ports/tables.py:44
+#: dashboards/project/networks/templates/networks/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:30
+#: dashboards/project/volumes/tables.py:154
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:17
+msgid "Status"
+msgstr "Status"
+
+#: dashboards/admin/instances/tables.py:83
+#: dashboards/project/instances/tables.py:302
+msgid "Task"
+msgstr "Task"
+
+#: dashboards/admin/instances/tables.py:90
+#: dashboards/project/instances/tables.py:309
+msgid "Power State"
+msgstr "Power State"
+
+#: dashboards/admin/instances/views.py:49
+#: dashboards/project/access_and_security/views.py:76
+#: dashboards/project/access_and_security/floating_ips/workflows.py:65
+msgid "Unable to retrieve instance list."
+msgstr "Unable to retrieve instance list."
+
+#: dashboards/admin/instances/views.py:63
+#: dashboards/admin/networks/views.py:48
+msgid "Unable to retrieve instance tenant information."
+msgstr "Unable to retrieve instance tenant information."
+
+#: dashboards/admin/instances/views.py:80
+#: dashboards/project/instances/views.py:82
+msgid "Unable to retrieve instance size information."
+msgstr "Unable to retrieve instance size information."
+
+#: dashboards/admin/instances/templates/instances/index.html:6
+msgid "All Instances"
+msgstr "All Instances"
+
+#: dashboards/admin/networks/forms.py:36
+#: dashboards/admin/networks/tables.py:67
+#: dashboards/admin/projects/tables.py:65 dashboards/project/dashboard.py:40
+#: dashboards/project/instances/workflows.py:38
+msgid "Project"
+msgstr "Project"
+
+#: dashboards/admin/networks/forms.py:37 dashboards/admin/networks/forms.py:74
+#: dashboards/admin/networks/tables.py:72
+#: dashboards/project/networks/tables.py:98
+#: dashboards/project/networks/templates/networks/_detail_overview.html:17
+msgid "Shared"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:46 dashboards/admin/users/forms.py:42
+msgid "Select a project"
+msgstr "Select a project"
+
+#: dashboards/admin/networks/forms.py:58
+#, python-format
+msgid "Network %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:64
+#, python-format
+msgid "Failed to create network %s"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:71
+#: dashboards/admin/networks/templates/networks/ports/_update.html:12
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:12
+#: dashboards/admin/users/forms.py:114
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:11
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:12
+#: dashboards/project/instances/templates/instances/_detail_overview.html:11
+#: dashboards/project/networks/forms.py:39
+#: dashboards/project/networks/templates/networks/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_update.html:12
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:11
+msgid "ID"
+msgstr "ID"
+
+#: dashboards/admin/networks/forms.py:82
+#: dashboards/project/networks/forms.py:48
+#, python-format
+msgid "Network %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:87
+#: dashboards/project/networks/forms.py:53
+#, python-format
+msgid "Failed to update network %s"
+msgstr ""
+
+#: dashboards/admin/networks/panel.py:25
+#: dashboards/admin/networks/tables.py:35
+#: dashboards/admin/networks/tables.py:80
+#: dashboards/admin/networks/templates/networks/index.html:3
+#: dashboards/admin/networks/templates/networks/index.html:6
+#: dashboards/project/instances/workflows.py:412
+#: dashboards/project/networks/panel.py:25
+#: dashboards/project/networks/tables.py:44
+#: dashboards/project/networks/tables.py:106
+#: dashboards/project/networks/templates/networks/index.html:3
+#: dashboards/project/networks/templates/networks/index.html:6
+msgid "Networks"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:34
+#: dashboards/project/networks/tables.py:43
+#: dashboards/project/networks/templates/networks/subnets/index.html:3
+#: dashboards/project/networks/templates/networks/subnets/index.html:6
+msgid "Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:41
+#: dashboards/project/networks/tables.py:59
+#, python-format
+msgid "Failed to delete network %s"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:49
+#: dashboards/admin/networks/templates/networks/_create.html:8
+#: dashboards/admin/networks/templates/networks/_create.html:23
+#: dashboards/admin/networks/templates/networks/create.html:3
+#: dashboards/admin/networks/templates/networks/create.html:6
+#: dashboards/project/networks/tables.py:67
+#: dashboards/project/networks/workflows.py:111
+#: dashboards/project/networks/templates/networks/_create.html:7
+#: dashboards/project/networks/templates/networks/_create.html:22
+#: dashboards/project/networks/templates/networks/create.html:3
+#: dashboards/project/networks/templates/networks/create.html:6
+msgid "Create Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:56
+#: dashboards/admin/networks/templates/networks/_update.html:7
+#: dashboards/project/networks/tables.py:74
+#: dashboards/project/networks/templates/networks/_update.html:7
+msgid "Edit Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:68
+#: dashboards/admin/networks/ports/forms.py:33
+#: dashboards/project/networks/subnets/forms.py:35
+msgid "Network Name"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:71
+#: dashboards/project/networks/tables.py:97
+msgid "Subnets Associated"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:76
+#: dashboards/admin/networks/ports/tables.py:79
+#: dashboards/project/networks/tables.py:102
+#: dashboards/project/networks/ports/tables.py:46
+#: dashboards/project/networks/templates/networks/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:32
+msgid "Admin State"
+msgstr ""
+
+#: dashboards/admin/networks/views.py:60
+#: dashboards/project/networks/views.py:52
+msgid "Network list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:91
+#: dashboards/project/networks/views.py:109
+msgid "Subnet list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:103
+#: dashboards/project/networks/views.py:121
+msgid "Port list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:118
+#: dashboards/project/networks/views.py:134
+#: dashboards/project/networks/subnets/tables.py:96
+#, python-format
+msgid "Unable to retrieve details for network \"%s\"."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:36
+#: dashboards/project/networks/subnets/forms.py:39
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:13
+msgid "Network ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:42
+#: dashboards/admin/networks/ports/forms.py:74
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:34
+msgid "Device ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:54
+#, python-format
+msgid "Port %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:59
+#, python-format
+msgid "Failed to create a port for network %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:84
+#, python-format
+msgid "Port %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:89
+#, python-format
+msgid "Failed to update port %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:34
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:6
+msgid "Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:35
+#: dashboards/admin/networks/ports/tables.py:83
+#: dashboards/project/networks/ports/tables.py:53
+msgid "Ports"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:41
+#: dashboards/admin/networks/subnets/tables.py:39
+#: dashboards/project/networks/subnets/tables.py:51
+#, python-format
+msgid "Failed to delete subnet %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:51
+#: dashboards/admin/networks/templates/networks/ports/_create.html:8
+#: dashboards/admin/networks/templates/networks/ports/_create.html:23
+#: dashboards/admin/networks/templates/networks/ports/create.html:3
+#: dashboards/admin/networks/templates/networks/ports/create.html:6
+msgid "Create Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:62
+#: dashboards/admin/networks/templates/networks/ports/_update.html:7
+msgid "Edit Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:75
+#: dashboards/project/networks/ports/tables.py:42
+msgid "Fixed IPs"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:76
+#: dashboards/project/networks/ports/tables.py:43
+msgid "Device Attached"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tabs.py:32
+#: dashboards/admin/overview/panel.py:29
+#: dashboards/admin/overview/templates/overview/usage.html:6
+#: dashboards/project/images_and_snapshots/images/tabs.py:27
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:27
+#: dashboards/project/instances/tabs.py:26
+#: dashboards/project/networks/ports/tabs.py:32
+#: dashboards/project/networks/subnets/tabs.py:32
+#: dashboards/project/overview/panel.py:29
+#: dashboards/project/overview/templates/overview/usage.html:6
+#: dashboards/project/volumes/tabs.py:27
+msgid "Overview"
+msgstr "Overview"
+
+#: dashboards/admin/networks/ports/tabs.py:42
+#: dashboards/project/networks/ports/tabs.py:42
+msgid "Unable to retrieve port details."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:49
+#: dashboards/admin/networks/subnets/views.py:49
+#: dashboards/project/networks/subnets/views.py:54
+msgid "Unable to retrieve network."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:82
+msgid "Unable to retrieve port details"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/forms.py:43
+#, python-format
+msgid "Failed to retrieve network %s for a subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:32
+#: dashboards/project/networks/subnets/tables.py:44
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:6
+msgid "Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:33
+#: dashboards/admin/networks/subnets/tables.py:81
+#: dashboards/project/networks/subnets/tables.py:45
+#: dashboards/project/networks/subnets/tables.py:104
+msgid "Subnets"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:49
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:8
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:23
+#: dashboards/admin/networks/templates/networks/subnets/create.html:3
+#: dashboards/admin/networks/templates/networks/subnets/create.html:6
+#: dashboards/project/networks/workflows.py:53
+#: dashboards/project/networks/subnets/tables.py:61
+#: dashboards/project/networks/templates/networks/subnets/_create.html:8
+#: dashboards/project/networks/templates/networks/subnets/_create.html:23
+#: dashboards/project/networks/templates/networks/subnets/create.html:3
+#: dashboards/project/networks/templates/networks/subnets/create.html:6
+msgid "Create Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:60
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:7
+#: dashboards/project/networks/subnets/tables.py:72
+#: dashboards/project/networks/templates/networks/subnets/_update.html:7
+msgid "Edit Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:72
+#: dashboards/project/access_and_security/security_groups/forms.py:91
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:15
+msgid "CIDR"
+msgstr "CIDR"
+
+#: dashboards/admin/networks/subnets/tables.py:73
+#: dashboards/project/networks/workflows.py:66
+#: dashboards/project/networks/subnets/forms.py:53
+#: dashboards/project/networks/subnets/tables.py:85
+msgid "IP Version"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:74
+#: dashboards/project/networks/subnets/forms.py:54
+#: dashboards/project/networks/subnets/forms.py:104
+#: dashboards/project/networks/subnets/tables.py:86
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:19
+msgid "Gateway IP"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/views.py:82
+#: dashboards/project/networks/subnets/views.py:86
+msgid "Unable to retrieve subnet details"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_create.html:18
+#: dashboards/project/networks/templates/networks/_create.html:17
+msgid "Select a name for your network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:16
+#: dashboards/admin/networks/templates/networks/ports/_update.html:21
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:25
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:17
+#: dashboards/project/instances/templates/instances/_update.html:16
+#: dashboards/project/networks/templates/networks/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_update.html:25
+#: dashboards/settings/ec2/templates/ec2/download_form.html:17
+#: dashboards/settings/project/templates/project/_openrc.html:24
+#: dashboards/settings/user/templates/user/_settings.html:17
+msgid "Description:"
+msgstr "Description:"
+
+#: dashboards/admin/networks/templates/networks/_update.html:17
+#: dashboards/project/networks/templates/networks/_update.html:17
+msgid "You may update the editable properties of your network here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:22
+#: dashboards/admin/networks/templates/networks/ports/_update.html:27
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:31
+#: dashboards/project/instances/templates/instances/_update.html:22
+#: dashboards/project/networks/templates/networks/_update.html:22
+#: dashboards/project/networks/templates/networks/subnets/_update.html:31
+msgid "Save Changes"
+msgstr "Save Changes"
+
+#: dashboards/admin/networks/templates/networks/update.html:3
+#: dashboards/admin/networks/templates/networks/update.html:6
+#: dashboards/project/networks/templates/networks/update.html:3
+#: dashboards/project/networks/templates/networks/update.html:6
+msgid "Update Network"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_create.html:18
+msgid ""
+"You can create a port for the network. If you specify device ID to be "
+"attached, the device specified will be attached to the port created."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_update.html:22
+msgid "You may update the editable properties of your port here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/update.html:3
+#: dashboards/admin/networks/templates/networks/ports/update.html:6
+msgid "Update Port"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:18
+#: dashboards/project/networks/templates/networks/subnets/_create.html:18
+msgid ""
+"You can create a subnet for the network. Any network address can be "
+"specified unless the network address does not overlap other subnets in the "
+"network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:14
+#: dashboards/project/networks/workflows.py:58
+#: dashboards/project/networks/subnets/forms.py:45
+#: dashboards/project/networks/subnets/tables.py:84
+#: dashboards/project/networks/templates/networks/subnets/_update.html:14
+msgid "Network Address"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:17
+#: dashboards/project/networks/templates/networks/subnets/_update.html:16
+msgid "IP version"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:26
+#: dashboards/project/networks/templates/networks/subnets/_update.html:26
+msgid "You may update the editable properties of your subnet here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/index.html:3
+#: dashboards/admin/networks/templates/networks/subnets/index.html:6
+#: dashboards/project/networks/templates/networks/detail.html:3
+msgid "Network Detail"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/update.html:3
+#: dashboards/admin/networks/templates/networks/subnets/update.html:6
+#: dashboards/project/networks/templates/networks/subnets/update.html:3
+#: dashboards/project/networks/templates/networks/subnets/update.html:6
+msgid "Update Subnet"
+msgstr ""
+
+#: dashboards/admin/overview/templates/overview/usage.html:3
+msgid "Usage Overview"
+msgstr "Usage Overview"
+
+#: dashboards/admin/overview/templates/overview/usage.html:12
+msgid "Monitoring"
+msgstr "Monitoring"
+
+#: dashboards/admin/projects/panel.py:29
+#: dashboards/admin/projects/tables.py:66
+#: dashboards/admin/projects/tables.py:95
+#: dashboards/admin/projects/templates/projects/index.html:8
+#: templates/403.html:24 templates/404.html:23 templates/500.html:23
+msgid "Projects"
+msgstr "Projects"
+
+#: dashboards/admin/projects/tables.py:19
+msgid "Modify Users"
+msgstr "Modify Users"
+
+#: dashboards/admin/projects/tables.py:32
+msgid "View Usage"
+msgstr "View Usage"
+
+#: dashboards/admin/projects/tables.py:39
+#: dashboards/admin/projects/templates/projects/_create.html:8
+#: dashboards/admin/projects/templates/projects/_create.html:23
+#: dashboards/admin/projects/templates/projects/create.html:6
+msgid "Create Project"
+msgstr "Create Project"
+
+#: dashboards/admin/projects/tables.py:46
+#: dashboards/admin/projects/workflows.py:269
+#: dashboards/admin/projects/templates/projects/update.html:3
+#: dashboards/admin/projects/templates/projects/update.html:6
+msgid "Edit Project"
+msgstr "Edit Project"
+
+#: dashboards/admin/projects/tables.py:90
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:60
+#: dashboards/project/networks/templates/networks/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:15
+msgid "Project ID"
+msgstr "Project ID"
+
+#: dashboards/admin/projects/tables.py:91
+#: dashboards/admin/projects/workflows.py:76
+#: dashboards/admin/projects/workflows.py:251
+#: dashboards/admin/services/tables.py:42 dashboards/admin/users/tables.py:40
+#: dashboards/admin/users/tables.py:115
+msgid "Enabled"
+msgstr "Enabled"
+
+#: dashboards/admin/projects/tables.py:104
+msgid "Remove"
+msgstr "Remove"
+
+#: dashboards/admin/projects/tables.py:105
+msgid "Removed"
+msgstr "Removed"
+
+#: dashboards/admin/projects/tables.py:106 dashboards/admin/users/tables.py:41
+#: dashboards/admin/users/tables.py:75
+#: dashboards/project/instances/workflows.py:39
+msgid "User"
+msgstr "User"
+
+#: dashboards/admin/projects/tables.py:107 dashboards/admin/users/panel.py:29
+#: dashboards/admin/users/tables.py:42 dashboards/admin/users/tables.py:76
+#: dashboards/admin/users/tables.py:122
+#: dashboards/admin/users/templates/users/index.html:8
+msgid "Users"
+msgstr "Users"
+
+#: dashboards/admin/projects/tables.py:125
+msgid "Unable to retrieve role information."
+msgstr "Unable to retrieve role information."
+
+#: dashboards/admin/projects/tables.py:130
+msgid "Roles"
+msgstr "Roles"
+
+#: dashboards/admin/projects/tables.py:134
+msgid "Users For Project"
+msgstr "Users For Project"
+
+#: dashboards/admin/projects/tables.py:142
+msgid "Add To Project"
+msgstr "Add To Project"
+
+#: dashboards/admin/projects/tables.py:154
+msgid "Add New Users"
+msgstr "Add New Users"
+
+#: dashboards/admin/projects/views.py:67
+msgid "Unable to retrieve project information."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:87
+msgid "Unable to retrieve project list."
+msgstr "Unable to retrieve project list."
+
+#: dashboards/admin/projects/views.py:110
+msgid "Unable to retrieve users."
+msgstr "Unable to retrieve users."
+
+#: dashboards/admin/projects/views.py:154
+msgid "Unable to retrieve default quota values."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:182
+msgid "Unable to retrieve project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:37
+msgid "Injected File Content Bytes"
+msgstr "Injected File Content Bytes"
+
+#: dashboards/admin/projects/workflows.py:38
+msgid "Metadata Items"
+msgstr "Metadata Items"
+
+#: dashboards/admin/projects/workflows.py:41
+msgid "Injected Files"
+msgstr "Injected Files"
+
+#: dashboards/admin/projects/workflows.py:44
+#: dashboards/admin/volumes/panel.py:9 dashboards/admin/volumes/tables.py:15
+#: dashboards/admin/volumes/templates/volumes/index.html:3
+#: dashboards/admin/volumes/templates/volumes/index.html:6
+#: dashboards/project/volumes/panel.py:25
+#: dashboards/project/volumes/tables.py:38
+#: dashboards/project/volumes/tables.py:171
+#: dashboards/project/volumes/tables.py:183
+#: dashboards/project/volumes/templates/volumes/index.html:3
+#: dashboards/project/volumes/templates/volumes/index.html:6
+msgid "Volumes"
+msgstr "Volumes"
+
+#: dashboards/admin/projects/workflows.py:45
+msgid "Gigabytes"
+msgstr "Gigabytes"
+
+#: dashboards/admin/projects/workflows.py:46
+msgid "RAM (MB)"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:47
+#: dashboards/project/access_and_security/floating_ips/tables.py:50
+#: dashboards/project/access_and_security/floating_ips/tables.py:128
+msgid "Floating IPs"
+msgstr "Floating IPs"
+
+#: dashboards/admin/projects/workflows.py:50
+msgid "Quota"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:52
+msgid "From here you can set quotas (max limits) for the project."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:81
+#: dashboards/admin/projects/workflows.py:254
+msgid "Project Info"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:82
+#: dashboards/admin/projects/templates/projects/_create.html:18
+msgid "From here you can create a new project to organize users."
+msgstr "From here you can create a new project to organize users."
+
+#: dashboards/admin/projects/workflows.py:101
+msgid "Unable to retrieve user list. Please try again later."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:155
+#: dashboards/admin/projects/templates/projects/_update_members.html:16
+msgid "Project Members"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:169
+#: dashboards/admin/users/views.py:47
+msgid "Unable to retrieve user list."
+msgstr "Unable to retrieve user list."
+
+#: dashboards/admin/projects/workflows.py:180
+msgid "Add Project"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:181
+msgid "Finish"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:182
+#, python-format
+msgid "Created new project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:183
+#, python-format
+msgid "Unable to create project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:227
+#, python-format
+msgid "Failed to add %s project members and set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:246
+msgid "Unable to set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:256
+msgid "From here you can edit the project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:271
+#, python-format
+msgid "Modified project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:272
+#, python-format
+msgid "Unable to modify project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:342
+#, python-format
+msgid "Failed to modify %s project members and update project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:363
+msgid ""
+"Modified project information and members, but unable to modify project "
+"quotas."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:8
+#: dashboards/admin/projects/templates/projects/add_user.html:3
+#: dashboards/admin/projects/templates/projects/add_user.html:6
+msgid "Add User To Project"
+msgstr "Add User To Project"
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:18
+msgid "Select the user role for the project."
+msgstr "Select the user role for the project."
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:23
+msgid "Add"
+msgstr "Add"
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:7
+#, python-format
+msgid "Create User for project '%(tenant_name)s'."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:18
+msgid "From here you can create a new user to add to this project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:23
+#: dashboards/admin/users/tables.py:20
+#: dashboards/admin/users/templates/users/_create.html:7
+#: dashboards/admin/users/templates/users/_create.html:22
+#: dashboards/admin/users/templates/users/create.html:7
+msgid "Create User"
+msgstr "Create User"
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:7
+#: dashboards/admin/projects/templates/projects/_quotas.html:22
+msgid "Update Quota"
+msgstr "Update Quota"
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:17
+#, python-format
+msgid ""
+"From here you can edit quotas (max limits) for the project %(tenant.name)s."
+msgstr ""
+"From here you can edit quotas (max limits) for the project %(tenant.name)s."
+
+#: dashboards/admin/projects/templates/projects/_update.html:8
+#: dashboards/admin/projects/templates/projects/_update.html:23
+#: dashboards/admin/projects/templates/projects/quotas.html:6
+msgid "Update Project"
+msgstr "Update Project"
+
+#: dashboards/admin/projects/templates/projects/_update.html:18
+msgid "From here you can edit a project."
+msgstr "From here you can edit a project."
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:7
+msgid ""
+"From here you can add and remove members to this project from the list of "
+"all available users."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:10
+msgid "All Users"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:25
+#: dashboards/admin/projects/templates/projects/_update_members.html:32
+msgid "No users found."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/create_user.html:3
+#: dashboards/admin/projects/templates/projects/create_user.html:6
+msgid "Add New User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:3
+msgid "Project Usage Overview"
+msgstr "Project Usage Overview"
+
+#: dashboards/admin/projects/templates/projects/usage.html:7
+msgid "Project Usage"
+msgstr "Project Usage"
+
+#: dashboards/admin/projects/templates/projects/users.html:7
+msgid "Users for Project"
+msgstr "Users for Project"
+
+#: dashboards/admin/quotas/panel.py:29 dashboards/admin/quotas/tables.py:36
+msgid "Quotas"
+msgstr "Quotas"
+
+#: dashboards/admin/quotas/tables.py:28
+msgid "Quota Name"
+msgstr "Quota Name"
+
+#: dashboards/admin/quotas/tables.py:29
+msgid "Limit"
+msgstr "Limit"
+
+#: dashboards/admin/quotas/views.py:46
+msgid "Unable to get quota info."
+msgstr "Unable to get quota info."
+
+#: dashboards/admin/quotas/templates/quotas/index.html:8
+msgid "Default Quotas"
+msgstr "Default Quotas"
+
+#: dashboards/admin/services/panel.py:29
+#: dashboards/admin/services/tables.py:47
+#: dashboards/admin/services/templates/services/index.html:8
+msgid "Services"
+msgstr "Services"
+
+#: dashboards/admin/services/tables.py:37
+msgid "Id"
+msgstr "Id"
+
+#: dashboards/admin/services/tables.py:39
+msgid "Service"
+msgstr "Service"
+
+#: dashboards/admin/users/forms.py:54
+msgid "Passwords do not match."
+msgstr "Passwords do not match."
+
+#: dashboards/admin/users/forms.py:62 dashboards/admin/users/forms.py:115
+#: dashboards/admin/users/tables.py:108
+msgid "User Name"
+msgstr "User Name"
+
+#: dashboards/admin/users/forms.py:63 dashboards/admin/users/forms.py:116
+#: dashboards/admin/users/tables.py:109
+msgid "Email"
+msgstr "Email"
+
+#: dashboards/admin/users/forms.py:65 dashboards/admin/users/forms.py:117
+msgid "Password"
+msgstr "Password"
+
+#: dashboards/admin/users/forms.py:70 dashboards/admin/users/forms.py:124
+msgid "Confirm Password"
+msgstr "Confirm Password"
+
+#: dashboards/admin/users/forms.py:73 dashboards/admin/users/forms.py:127
+msgid "Primary Project"
+msgstr "Primary Project"
+
+#: dashboards/admin/users/forms.py:75
+msgid "Role"
+msgstr "Role"
+
+#: dashboards/admin/users/forms.py:96
+#, python-format
+msgid "User \"%s\" was successfully created."
+msgstr "User \"%s\" was successfully created."
+
+#: dashboards/admin/users/forms.py:106
+msgid "Unable to add userto primary project."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:110
+msgid "Unable to create user."
+msgstr "Unable to create user."
+
+#: dashboards/admin/users/forms.py:151
+msgid "name"
+msgstr "name"
+
+#: dashboards/admin/users/forms.py:151
+msgid "email"
+msgstr "email"
+
+#: dashboards/admin/users/forms.py:160
+msgid "primary project"
+msgstr "primary project"
+
+#: dashboards/admin/users/forms.py:173
+#, python-format
+msgid "The user %s has no role defined for"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:181
+msgid "password"
+msgstr "password"
+
+#: dashboards/admin/users/forms.py:190
+msgid "User has been updated successfully."
+msgstr "User has been updated successfully."
+
+#: dashboards/admin/users/forms.py:194
+#, python-format
+msgid "Unable to update %(attributes)s for the user."
+msgstr "Unable to update %(attributes)s for the user."
+
+#: dashboards/admin/users/tables.py:32
+#: dashboards/project/images_and_snapshots/images/tables.py:68
+msgid "Edit"
+msgstr "Edit"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Enable"
+msgstr "Enable"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Disable"
+msgstr "Disable"
+
+#: dashboards/admin/users/tables.py:40
+msgid "Disabled"
+msgstr "Disabled"
+
+#: dashboards/admin/users/tables.py:63
+msgid "You cannot disable the user you are currently logged in as."
+msgstr "You cannot disable the user you are currently logged in as."
+
+#: dashboards/admin/users/tables.py:114
+msgid "User ID"
+msgstr "User ID"
+
+#: dashboards/admin/users/views.py:70
+msgid "Unable to update user."
+msgstr "Unable to update user."
+
+#: dashboards/admin/users/views.py:104
+msgid "Unable to retrieve user roles."
+msgstr "Unable to retrieve user roles."
+
+#: dashboards/admin/users/templates/users/_create.html:17
+msgid "From here you can create a new user and assign them to a project."
+msgstr "From here you can create a new user and assign them to a project."
+
+#: dashboards/admin/users/templates/users/_update.html:7
+#: dashboards/admin/users/templates/users/_update.html:22
+#: dashboards/admin/users/templates/users/update.html:7
+msgid "Update User"
+msgstr "Update User"
+
+#: dashboards/admin/users/templates/users/_update.html:17
+msgid ""
+"From here you can edit the user's details, including their default project."
+msgstr ""
+"From here you can edit the user's details, including their default project."
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:3
+#: dashboards/project/volumes/templates/volumes/detail.html:3
+msgid "Volume Details"
+msgstr "Volume Details"
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:6
+#: dashboards/project/volumes/templates/volumes/detail.html:6
+msgid "Volume Detail"
+msgstr "Volume Detail"
+
+#: dashboards/project/dashboard.py:24
+msgid "Manage Compute"
+msgstr "Manage Compute"
+
+#: dashboards/project/dashboard.py:35
+msgid "Object Store"
+msgstr "Object Store"
+
+#: dashboards/project/access_and_security/panel.py:26
+#: dashboards/project/instances/workflows.py:348
+msgid "Access & Security"
+msgstr "Access & Security"
+
+#: dashboards/project/access_and_security/views.py:51
+msgid "Unable to retrieve keypair list."
+msgstr "Unable to retrieve keypair list."
+
+#: dashboards/project/access_and_security/views.py:60
+#: dashboards/project/access_and_security/security_groups/views.py:74
+msgid "Unable to retrieve security groups."
+msgstr "Unable to retrieve security groups."
+
+#: dashboards/project/access_and_security/views.py:69
+#: dashboards/project/access_and_security/floating_ips/workflows.py:49
+msgid "Unable to retrieve floating IP addresses."
+msgstr "Unable to retrieve floating IP addresses."
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:32
+msgid "Pool"
+msgstr "Pool"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:43
+#, python-format
+msgid "Allocated Floating IP %(ip)s."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:47
+msgid "Unable to allocate Floating IP."
+msgstr "Unable to allocate Floating IP."
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:37
+msgid "Allocate IP To Project"
+msgstr "Allocate IP To Project"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:47
+msgid "Release"
+msgstr "Release"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:48
+msgid "Released"
+msgstr "Released"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:49
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:22
+msgid "Floating IP"
+msgstr "Floating IP"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:6
+#: dashboards/project/instances/tables.py:219
+msgid "Associate Floating IP"
+msgstr "Associate Floating IP"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:76
+msgid "Disassociate Floating IP"
+msgstr "Disassociate Floating IP"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:90
+#, python-format
+msgid "Successfully disassociated Floating IP: %s"
+msgstr "Successfully disassociated Floating IP: %s"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:94
+msgid "Unable to disassociate floating IP."
+msgstr "Unable to disassociate floating IP."
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:114
+#: dashboards/project/access_and_security/floating_ips/workflows.py:36
+#: dashboards/project/instances/tables.py:69
+#: dashboards/project/instances/tables.py:89
+#: dashboards/project/instances/tables.py:106
+#: dashboards/project/instances/tables.py:135
+#: dashboards/project/volumes/tables.py:206
+msgid "Instance"
+msgstr "Instance"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:117
+msgid "Floating IP Pool"
+msgstr "Floating IP Pool"
+
+#: dashboards/project/access_and_security/floating_ips/views.py:65
+msgid "Unable to retrieve floating IP pools."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:68
+msgid "No floating IP pools available."
+msgstr "No floating IP pools available."
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:40
+msgid "Select the IP address you wish to associate with the selected instance."
+msgstr ""
+"Select the IP address you wish to associate with the selected instance."
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:53
+msgid "Select an IP address"
+msgstr "Select an IP address"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:55
+msgid "No IP addresses available"
+msgstr "No IP addresses available"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:76
+#: dashboards/project/volumes/forms.py:160
+msgid "Select an instance"
+msgstr "Select an instance"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:78
+#: dashboards/project/volumes/forms.py:162
+msgid "No instances available"
+msgstr "No instances available"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:97
+msgid "Manage Floating IP Associations"
+msgstr "Manage Floating IP Associations"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:98
+msgid "Associate"
+msgstr "Associate"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:99
+#, python-format
+msgid "IP address %s associated."
+msgstr "IP address %s associated."
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:100
+#, python-format
+msgid "Unable to associate IP address %s."
+msgstr "Unable to associate IP address %s."
+
+#: dashboards/project/access_and_security/keypairs/forms.py:38
+#: dashboards/project/access_and_security/keypairs/forms.py:49
+#: dashboards/project/access_and_security/keypairs/tables.py:52
+msgid "Keypair Name"
+msgstr "Keypair Name"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:40
+msgid ""
+"Keypair names may only contain letters, numbers, underscores and hyphens."
+msgstr ""
+"Keypair names may only contain letters, numbers, underscores and hyphens."
+
+#: dashboards/project/access_and_security/keypairs/forms.py:51
+msgid "Public Key"
+msgstr "Public Key"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:60
+#, python-format
+msgid "Successfully imported public key: %s"
+msgstr "Successfully imported public key: %s"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:65
+msgid "Unable to import keypair."
+msgstr "Unable to import keypair."
+
+#: dashboards/project/access_and_security/keypairs/tables.py:30
+#: dashboards/project/instances/tables.py:295
+#: dashboards/project/instances/workflows.py:335
+msgid "Keypair"
+msgstr "Keypair"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:31
+#: dashboards/project/access_and_security/keypairs/tables.py:60
+msgid "Keypairs"
+msgstr "Keypairs"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:39
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html:6
+msgid "Import Keypair"
+msgstr "Import Keypair"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:46
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html:6
+msgid "Create Keypair"
+msgstr "Create Keypair"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:53
+msgid "Fingerprint"
+msgstr "Fingerprint"
+
+#: dashboards/project/access_and_security/keypairs/views.py:74
+#, python-format
+msgid "Unable to create keypair: %(exc)s"
+msgstr "Unable to create keypair: %(exc)s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:46
+#, python-format
+msgid "Successfully created security group: %s"
+msgstr "Successfully created security group: %s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:52
+msgid "Unable to create security group."
+msgstr "Unable to create security group."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:57
+#: dashboards/project/access_and_security/security_groups/tables.py:93
+msgid "IP Protocol"
+msgstr "IP Protocol"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:61
+msgid "The protocol which this rule should be applied to."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:65
+#: dashboards/project/access_and_security/security_groups/forms.py:71
+#: dashboards/project/access_and_security/security_groups/tables.py:95
+msgid "From Port"
+msgstr "From Port"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:66
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP type in the range (-1: 255)"
+msgstr ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP type in the range (-1: 255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:72
+#: dashboards/project/images_and_snapshots/images/tables.py:115
+msgid "Type"
+msgstr "Type"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:74
+#: dashboards/project/access_and_security/security_groups/forms.py:80
+#: dashboards/project/access_and_security/security_groups/tables.py:96
+msgid "To Port"
+msgstr "To Port"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:75
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP code in the range (-1: 255)"
+msgstr ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP code in the range (-1: 255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:81
+msgid "Code"
+msgstr "Code"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:84
+msgid "Source Group"
+msgstr "Source Group"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:86
+msgid ""
+"To specify an allowed IP range, select CIDR. To allow access from all "
+"members of another security group select Source Group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:94
+msgid "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+msgstr "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:121
+msgid "The ICMP type is invalid."
+msgstr "The ICMP type is invalid."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:124
+msgid "The ICMP code is invalid."
+msgstr "The ICMP code is invalid."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:127
+msgid "The ICMP type not in range (-1, 255)"
+msgstr "The ICMP type not in range (-1, 255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:130
+msgid "The ICMP code not in range (-1, 255)"
+msgstr "The ICMP code not in range (-1, 255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:134
+msgid "The \"from\" port number is invalid."
+msgstr "The \"from\" port number is invalid."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:137
+msgid "The \"to\" port number is invalid."
+msgstr "The \"to\" port number is invalid."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:140
+msgid ""
+"The \"to\" port number must be greater than or equal to the \"from\" port "
+"number."
+msgstr ""
+"The \"to\" port number must be greater than or equal to the \"from\" port "
+"number."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:146
+msgid "Either CIDR or Source Group may be specified, but not both."
+msgstr "Either CIDR or Source Group may be specified, but not both."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:168
+#, python-format
+msgid "Successfully added rule: %s"
+msgstr "Successfully added rule: %s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:173
+msgid "Unable to add rule to security group."
+msgstr "Unable to add rule to security group."
+
+#: dashboards/project/access_and_security/security_groups/tables.py:31
+msgid "Security Group"
+msgstr "Security Group"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:32
+#: dashboards/project/access_and_security/security_groups/tables.py:66
+#: dashboards/project/instances/workflows.py:340
+#: dashboards/project/instances/templates/instances/_detail_overview.html:49
+msgid "Security Groups"
+msgstr "Security Groups"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:45
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html:6
+msgid "Create Security Group"
+msgstr "Create Security Group"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:52
+msgid "Edit Rules"
+msgstr "Edit Rules"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:72
+msgid "Rule"
+msgstr "Rule"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:73
+msgid "Rules"
+msgstr "Rules"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:97
+msgid "Source"
+msgstr "Source"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:107
+msgid "Security Group Rules"
+msgstr "Security Group Rules"
+
+#: dashboards/project/access_and_security/security_groups/views.py:60
+msgid "Unable to retrieve security group."
+msgstr "Unable to retrieve security group."
+
+#: dashboards/project/access_and_security/security_groups/views.py:80
+#, python-format
+msgid "%s (current)"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/index.html:6
+msgid "Access &amp; Security"
+msgstr "Access &amp; Security"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:8
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html:3
+msgid "Allocate Floating IP"
+msgstr "Allocate Floating IP"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:18
+msgid "Allocate a floating IP from a given floating ip pool."
+msgstr "Allocate a floating IP from a given floating ip pool."
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:20
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:19
+msgid "Project Quotas"
+msgstr "Project Quotas"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:31
+msgid "Allocate IP"
+msgstr "Allocate IP"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:17
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:17
+msgid ""
+"Keypairs are ssh credentials which are injected into images when they are "
+"launched. Creating a new key pair registers the public key and downloads the "
+"private key (a .pem file)."
+msgstr ""
+"Keypairs are ssh credentials which are injected into images when they are "
+"launched. Creating a new key pair registers the public key and downloads the "
+"private key (a .pem file)."
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:18
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:18
+msgid "Protect and use the key as you would any normal ssh private key."
+msgstr "Protect and use the key as you would any normal ssh private key."
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:6
+msgid "Download Keypair"
+msgstr "Download Keypair"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:11
+#, python-format
+msgid ""
+"The keypair &quot;%(keypair_name)s&quot; should download automatically. If "
+"not use the link below."
+msgstr ""
+"The keypair \"%(keypair_name)s\" should download automatically. If not use "
+"the link below."
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:15
+#, python-format
+msgid "Download keypair &quot;%(keypair_name)s&quot;"
+msgstr "Download keypair \"%(keypair_name)s\""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:18
+msgid "From here you can create a new security group"
+msgstr "From here you can create a new security group"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:9
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html:6
+msgid "Edit Security Group Rules"
+msgstr "Edit Security Group Rules"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:12
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:19
+msgid "Add Rule"
+msgstr "Add Rule"
+
+#: dashboards/project/containers/browsers.py:26
+msgid "Swift"
+msgstr ""
+
+#: dashboards/project/containers/browsers.py:29
+#: dashboards/project/containers/tables.py:40
+msgid "Container"
+msgstr "Container"
+
+#: dashboards/project/containers/forms.py:39
+msgid "Slash is not an allowed character."
+msgstr "Slash is not an allowed character."
+
+#: dashboards/project/containers/forms.py:49
+#: dashboards/project/containers/tables.py:121
+msgid "Container Name"
+msgstr "Container Name"
+
+#: dashboards/project/containers/forms.py:57
+msgid "Container created successfully."
+msgstr "Container created successfully."
+
+#: dashboards/project/containers/forms.py:68
+msgid "Folder created successfully."
+msgstr "Folder created successfully."
+
+#: dashboards/project/containers/forms.py:71
+msgid "Unable to create container."
+msgstr "Unable to create container."
+
+#: dashboards/project/containers/forms.py:79
+#: dashboards/project/containers/tables.py:253
+msgid "Object Name"
+msgstr "Object Name"
+
+#: dashboards/project/containers/forms.py:81
+msgid "File"
+msgstr "File"
+
+#: dashboards/project/containers/forms.py:95
+msgid "Object was successfully uploaded."
+msgstr "Object was successfully uploaded."
+
+#: dashboards/project/containers/forms.py:98
+msgid "Unable to upload object."
+msgstr "Unable to upload object."
+
+#: dashboards/project/containers/forms.py:102
+msgid "Destination container"
+msgstr "Destination container"
+
+#: dashboards/project/containers/forms.py:106
+msgid "Destination object name"
+msgstr "Destination object name"
+
+#: dashboards/project/containers/forms.py:137
+#: dashboards/project/containers/forms.py:163
+msgid "Unable to copy object."
+msgstr "Unable to copy object."
+
+#: dashboards/project/containers/forms.py:153
+#, python-format
+msgid "Copied \"%(orig)s\" to \"%(dest)s\" as \"%(new)s\"."
+msgstr "Copied \"%(orig)s\" to \"%(dest)s\" as \"%(new)s\"."
+
+#: dashboards/project/containers/panel.py:29
+#: dashboards/project/containers/tables.py:41
+#: dashboards/project/containers/tables.py:128
+#: dashboards/project/containers/templates/containers/index.html:7
+msgid "Containers"
+msgstr "Containers"
+
+#: dashboards/project/containers/tables.py:62
+#: dashboards/project/containers/templates/containers/_create.html:7
+#: dashboards/project/containers/templates/containers/_create.html:22
+#: dashboards/project/containers/templates/containers/create.html:6
+msgid "Create Container"
+msgstr "Create Container"
+
+#: dashboards/project/containers/tables.py:69
+msgid "View Container"
+msgstr "View Container"
+
+#: dashboards/project/containers/tables.py:81
+#: dashboards/project/containers/templates/containers/_upload.html:23
+#: dashboards/project/containers/templates/containers/upload.html:3
+msgid "Upload Object"
+msgstr "Upload Object"
+
+#: dashboards/project/containers/tables.py:137
+#: dashboards/project/containers/tables.py:156
+msgid "Object"
+msgstr "Object"
+
+#: dashboards/project/containers/tables.py:138
+#: dashboards/project/containers/tables.py:157
+#: dashboards/project/containers/tables.py:263
+msgid "Objects"
+msgstr "Objects"
+
+#: dashboards/project/containers/tables.py:149
+msgid "Folder"
+msgstr "Folder"
+
+#: dashboards/project/containers/tables.py:150
+msgid "Folders"
+msgstr "Folders"
+
+#: dashboards/project/containers/tables.py:163
+msgid "Copy"
+msgstr "Copy"
+
+#: dashboards/project/containers/tables.py:176
+msgid "Download"
+msgstr "Download"
+
+#: dashboards/project/containers/tables.py:232
+msgid "Create Folder"
+msgstr "Create Folder"
+
+#: dashboards/project/containers/views.py:53
+msgid "Unable to retrieve container list."
+msgstr "Unable to retrieve container list."
+
+#: dashboards/project/containers/views.py:82
+msgid "Unable to retrieve object list."
+msgstr "Unable to retrieve object list."
+
+#: dashboards/project/containers/views.py:166
+msgid "Unable to retrieve object."
+msgstr "Unable to retrieve object."
+
+#: dashboards/project/containers/views.py:200
+msgid "Unable to list containers."
+msgstr "Unable to list containers."
+
+#: dashboards/project/containers/templates/containers/_copy.html:7
+#: dashboards/project/containers/templates/containers/_copy.html:22
+#: dashboards/project/containers/templates/containers/copy.html:3
+#: dashboards/project/containers/templates/containers/copy.html:6
+msgid "Copy Object"
+msgstr "Copy Object"
+
+#: dashboards/project/containers/templates/containers/_copy.html:17
+msgid ""
+"Make a new copy of an existing object to store in this or another container. "
+"You may also specify a path at which the new copy should live inside of the "
+"selected container."
+msgstr ""
+"Make a new copy of an existing object to store in this or another container. "
+"You may also specify a path at which the new copy should live inside of the "
+"selected container."
+
+#: dashboards/project/containers/templates/containers/_create.html:17
+msgid ""
+"A container is a storage compartment for your data and provides a way for "
+"you to organize your data. You can think of a container as a folder in "
+"Windows &reg; or a directory in UNIX &reg;. The primary difference between a "
+"container and these other file system concepts is that containers cannot be "
+"nested. You can, however, create an unlimited number of containers within "
+"your account. Data must be stored in a container so you must have at least "
+"one container defined in your account prior to uploading data."
+msgstr ""
+"A container is a storage compartment for your data and provides a way for "
+"you to organize your data. You can think of a container as a folder in "
+"Windows &reg; or a directory in UNIX &reg;. The primary difference between a "
+"container and these other file system concepts is that containers cannot be "
+"nested. You can, however, create an unlimited number of containers within "
+"your account. Data must be stored in a container so you must have at least "
+"one container defined in your account prior to uploading data."
+
+#: dashboards/project/containers/templates/containers/_upload.html:8
+msgid "Upload Object To Container"
+msgstr "Upload Object To Container"
+
+#: dashboards/project/containers/templates/containers/_upload.html:18
+msgid ""
+"An object is the basic storage entity and any optional metadata that "
+"represents the files you store in the OpenStack Object Storage system. When "
+"you upload data to OpenStack Object Storage, the data is stored as-is (no "
+"compression or encryption) and consists of a location (container), the "
+"object's name, and any metadata consisting of key/value pairs."
+msgstr ""
+"An object is the basic storage entity and any optional metadata that "
+"represents the files you store in the OpenStack Object Storage system. When "
+"you upload data to OpenStack Object Storage, the data is stored as-is (no "
+"compression or encryption) and consists of a location (container), the "
+"object's name, and any metadata consisting of key/value pairs."
+
+#: dashboards/project/containers/templates/containers/upload.html:6
+msgid "Upload Objects"
+msgstr "Upload Objects"
+
+#: dashboards/project/images_and_snapshots/panel.py:26
+msgid "Images & Snapshots"
+msgstr "Images & Snapshots"
+
+#: dashboards/project/images_and_snapshots/views.py:63
+msgid "Unable to retrieve images."
+msgstr "Unable to retrieve images."
+
+#: dashboards/project/images_and_snapshots/views.py:74
+msgid "Unable to retrieve snapshots."
+msgstr "Unable to retrieve snapshots."
+
+#: dashboards/project/images_and_snapshots/views.py:82
+#: dashboards/project/volumes/forms.py:65
+msgid "Unable to retrieve volume snapshots."
+msgstr "Unable to retrieve volume snapshots."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:42
+msgid "Image Location"
+msgstr "Image Location"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:43
+msgid "An external (HTTP) URL to load the image from."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:46
+#: dashboards/project/images_and_snapshots/images/forms.py:130
+#: dashboards/project/images_and_snapshots/images/tables.py:126
+msgid "Format"
+msgstr "Format"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:50
+msgid "AKI - Amazon Kernel Image"
+msgstr "AKI - Amazon Kernel Image"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:53
+msgid "AMI - Amazon Machine Image"
+msgstr "AMI - Amazon Machine Image"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:56
+msgid "ARI - Amazon Ramdisk Image"
+msgstr "ARI - Amazon Ramdisk Image"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:59
+msgid "ISO - Optical Disk Image"
+msgstr "ISO - Optical Disk Image"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:61
+msgid "QCOW2 - QEMU Emulator"
+msgstr "QCOW2 - QEMU Emulator"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:68
+msgid "Minimum Disk (GB)"
+msgstr "Minimum Disk (GB)"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:69
+#: dashboards/project/images_and_snapshots/images/forms.py:76
+msgid ""
+"The minimum disk size required to boot the image. If unspecified, this value "
+"defaults to 0 (no minimum)."
+msgstr ""
+"The minimum disk size required to boot the image. If unspecified, this value "
+"defaults to 0 (no minimum)."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:75
+msgid "Minimum Ram (MB)"
+msgstr "Minimum Ram (MB)"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:82
+#: dashboards/project/images_and_snapshots/images/forms.py:134
+#: dashboards/project/images_and_snapshots/images/tables.py:123
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:15
+msgid "Public"
+msgstr "Public"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:106
+#, python-format
+msgid "Your image %s has been queued for creation."
+msgstr "Your image %s has been queued for creation."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:110
+msgid "Unable to create new image."
+msgstr "Unable to create new image."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:116
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:48
+msgid "Kernel ID"
+msgstr "Kernel ID"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:121
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:52
+msgid "Ramdisk ID"
+msgstr "Ramdisk ID"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:126
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:44
+msgid "Architecture"
+msgstr "Architecture"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:138
+#, python-format
+msgid "Unable to update image \"%s\"."
+msgstr "Unable to update image \"%s\"."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:162
+msgid "Image was successfully updated."
+msgstr "Image was successfully updated."
+
+#: dashboards/project/images_and_snapshots/images/tables.py:34
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:33
+#: dashboards/project/instances/workflows.py:455
+msgid "Launch"
+msgstr "Launch"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:46
+#: dashboards/project/images_and_snapshots/images/tables.py:82
+#: dashboards/project/instances/workflows.py:168
+#: dashboards/project/instances/workflows.py:173
+msgid "Image"
+msgstr "Image"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:61
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:31
+msgid "Create Image"
+msgstr "Create Image"
+
+#: dashboards/project/images_and_snapshots/images/tabs.py:38
+msgid "Unable to retrieve image details."
+msgstr "Unable to retrieve image details."
+
+#: dashboards/project/images_and_snapshots/images/views.py:61
+msgid "Unable to retrieve image."
+msgstr "Unable to retrieve image."
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:37
+msgid "Instance ID"
+msgstr "Instance ID"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:40
+#: dashboards/project/volumes/forms.py:193
+msgid "Snapshot Name"
+msgstr "Snapshot Name"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:50
+#, python-format
+msgid "Snapshot \"%(name)s\" created for instance \"%(inst)s\""
+msgstr "Snapshot \"%(name)s\" created for instance \"%(inst)s\""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:56
+msgid "Unable to create snapshot."
+msgstr "Unable to create snapshot."
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:48
+#: dashboards/project/instances/workflows.py:107
+#: dashboards/project/instances/workflows.py:169
+msgid "Snapshot"
+msgstr "Snapshot"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:49
+msgid "Snapshots"
+msgstr "Snapshots"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:55
+msgid "Instance Snapshots"
+msgstr "Instance Snapshots"
+
+#: dashboards/project/images_and_snapshots/snapshots/views.py:53
+msgid "Unable to retrieve instance."
+msgstr "Unable to retrieve instance."
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:6
+msgid "Images &amp; Snapshots"
+msgstr "Images &amp; Snapshots"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:6
+msgid "Create An Image"
+msgstr "Create An Image"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:18
+msgid "Specify an image to upload to the Image Service."
+msgstr "Specify an image to upload to the Image Service."
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:21
+msgid ""
+"Currently only images available via an HTTP URL are supported. The image "
+"location must be accessible to the Image Service. Compressed image binaries "
+"are supported (.zip and .tar.gz.)"
+msgstr ""
+"Currently only images available via an HTTP URL are supported. The image "
+"location must be accessible to the Image Service. Compressed image binaries "
+"are supported (.zip and .tar.gz.)"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:24
+msgid "Please note: "
+msgstr "Please note: "
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:25
+#, fuzzy
+msgid ""
+"The Image Location field MUST be a valid and direct URL to the image binary. "
+"URLs that redirect or serve error pages will result in unusable images."
+msgstr ""
+"The Image Location field MUST be a valid and direct URL to the image binary. "
+"URLs that redirect or serve error pages will results in unusable images."
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:3
+msgid "Image Overview"
+msgstr "Image Overview"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:6
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:7
+#: dashboards/project/instances/templates/instances/_detail_overview.html:6
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:6
+msgid "Info"
+msgstr "Info"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:17
+msgid "Checksum"
+msgstr "Checksum"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:19
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:39
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:28
+msgid "Created"
+msgstr "Created"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:21
+msgid "Updated"
+msgstr "Updated"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:27
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:34
+#: dashboards/project/instances/templates/instances/_detail_overview.html:19
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:23
+msgid "Specs"
+msgstr "Specs"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:32
+msgid "Container Format"
+msgstr "Container Format"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:34
+msgid "Disk Format"
+msgstr "Disk Format"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:40
+msgid "Custom Properties"
+msgstr "Custom Properties"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:56
+msgid "Euca2ools state"
+msgstr "Euca2ools state"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:64
+msgid "Image Type"
+msgstr "Image Type"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html:4
+msgid "Image Detail "
+msgstr "Image Detail "
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:8
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:3
+#: dashboards/project/instances/tables.py:179
+#: dashboards/project/volumes/tables.py:76
+msgid "Create Snapshot"
+msgstr "Create Snapshot"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:18
+msgid "Snapshots preserve the disk state of a running instance."
+msgstr "Snapshots preserve the disk state of a running instance."
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:20
+#: dashboards/project/instances/workflows.py:75
+#: dashboards/project/instances/workflows.py:110
+#: dashboards/project/instances/templates/instances/_detail_overview.html:93
+#: dashboards/project/volumes/tables.py:37
+#: dashboards/project/volumes/tables.py:182
+msgid "Volume"
+msgstr "Volume"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:38
+#: dashboards/project/instances/templates/instances/_detail_overview.html:29
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:27
+msgid "GB"
+msgstr "GB"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:6
+msgid "Create a Snapshot"
+msgstr "Create a Snapshot"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:3
+#, fuzzy
+msgid "Volume Snapshot Details"
+msgstr "Volume Snapshots"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:6
+#, fuzzy
+msgid "Volume Snapshot Detail"
+msgstr "Volume Snapshot"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:34
+#: dashboards/project/instances/workflows.py:76
+msgid "Volume Snapshot"
+msgstr "Volume Snapshot"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:35
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:85
+msgid "Volume Snapshots"
+msgstr "Volume Snapshots"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:43
+#: dashboards/project/volumes/tables.py:59
+#: dashboards/project/volumes/templates/volumes/_create.html:8
+#: dashboards/project/volumes/templates/volumes/_create.html:55
+msgid "Create Volume"
+msgstr "Create Volume"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:80
+#: dashboards/project/volumes/forms.py:26
+msgid "Volume Name"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:41
+#, fuzzy
+msgid "Unable to retrieve snapshot details."
+msgstr "Unable to retrieve snapshots."
+
+#: dashboards/project/instances/forms.py:45
+#, python-format
+msgid "Instance \"%s\" updated."
+msgstr "Instance \"%s\" updated."
+
+#: dashboards/project/instances/forms.py:50
+msgid "Unable to update instance."
+msgstr "Unable to update instance."
+
+#: dashboards/project/instances/tables.py:67
+msgid "Terminate"
+msgstr "Terminate"
+
+#: dashboards/project/instances/tables.py:68
+msgid "Scheduled termination of"
+msgstr "Scheduled termination of"
+
+#: dashboards/project/instances/tables.py:87
+msgid "Reboot"
+msgstr "Reboot"
+
+#: dashboards/project/instances/tables.py:88
+msgid "Rebooted"
+msgstr "Rebooted"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Pause"
+msgstr "Pause"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Unpause"
+msgstr "Unpause"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Paused"
+msgstr "Paused"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Unpaused"
+msgstr "Unpaused"
+
+#: dashboards/project/instances/tables.py:133
+msgid "Suspend"
+msgstr "Suspend"
+
+#: dashboards/project/instances/tables.py:133
+msgid "Resume"
+msgstr "Resume"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Suspended"
+msgstr "Suspended"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Resumed"
+msgstr "Resumed"
+
+#: dashboards/project/instances/tables.py:162
+#: dashboards/project/instances/workflows.py:454
+#: dashboards/project/instances/templates/instances/launch.html:3
+#: dashboards/project/instances/templates/instances/launch.html:6
+msgid "Launch Instance"
+msgstr "Launch Instance"
+
+#: dashboards/project/instances/tables.py:169
+#: dashboards/project/instances/templates/instances/_update.html:7
+msgid "Edit Instance"
+msgstr "Edit Instance"
+
+#: dashboards/project/instances/tables.py:189
+msgid "VNC Console"
+msgstr "VNC Console"
+
+#: dashboards/project/instances/tables.py:204
+msgid "View Log"
+msgstr "View Log"
+
+#: dashboards/project/instances/tables.py:252
+#, python-format
+msgid "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disk"
+msgstr "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disk"
+
+#: dashboards/project/instances/tables.py:259
+#: dashboards/project/instances/tables.py:266
+msgid "Not available"
+msgstr "Not available"
+
+#: dashboards/project/instances/tabs.py:36
+msgid "Log"
+msgstr "Log"
+
+#: dashboards/project/instances/tabs.py:48
+#: dashboards/project/instances/views.py:106
+#, python-format
+msgid "Unable to get log for instance \"%s\"."
+msgstr "Unable to get log for instance \"%s\"."
+
+#: dashboards/project/instances/tabs.py:55
+msgid "VNC"
+msgstr "VNC"
+
+#: dashboards/project/instances/tabs.py:70
+#: dashboards/project/instances/views.py:122
+#, python-format
+msgid "Unable to get VNC console for instance \"%s\"."
+msgstr "Unable to get VNC console for instance \"%s\"."
+
+#: dashboards/project/instances/views.py:59
+msgid "Unable to retrieve instances."
+msgstr "Unable to retrieve instances."
+
+#: dashboards/project/instances/views.py:144
+msgid "Unable to retrieve instance details."
+msgstr "Unable to retrieve instance details."
+
+#: dashboards/project/instances/views.py:179
+#, python-format
+msgid "Unable to retrieve details for instance \"%s\"."
+msgstr "Unable to retrieve details for instance \"%s\"."
+
+#: dashboards/project/instances/workflows.py:53
+msgid "Project & User"
+msgstr "Project & User"
+
+#: dashboards/project/instances/workflows.py:66
+msgid "Don't boot from a volume."
+msgstr "Don't boot from a volume."
+
+#: dashboards/project/instances/workflows.py:67
+msgid "Boot from volume."
+msgstr "Boot from volume."
+
+#: dashboards/project/instances/workflows.py:68
+msgid "Boot from volume snapshot (creates a new volume)."
+msgstr "Boot from volume snapshot (creates a new volume)."
+
+#: dashboards/project/instances/workflows.py:72
+#: dashboards/project/instances/workflows.py:90
+msgid "Volume Options"
+msgstr "Volume Options"
+
+#: dashboards/project/instances/workflows.py:78
+#: dashboards/project/volumes/forms.py:126
+msgid "Device Name"
+msgstr "Device Name"
+
+#: dashboards/project/instances/workflows.py:81
+msgid "Volume mount point (e.g. 'vda' mounts at '/dev/vda')."
+msgstr "Volume mount point (e.g. 'vda' mounts at '/dev/vda')."
+
+#: dashboards/project/instances/workflows.py:83
+msgid "Delete on Terminate"
+msgstr "Delete on Terminate"
+
+#: dashboards/project/instances/workflows.py:86
+msgid "Delete volume on instance terminate"
+msgstr "Delete volume on instance terminate"
+
+#: dashboards/project/instances/workflows.py:100
+#, python-format
+msgid "Please choose a volume, or select %s."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:117
+msgid "Select Volume"
+msgstr "Select Volume"
+
+#: dashboards/project/instances/workflows.py:125
+msgid "Unable to retrieve list of volumes."
+msgstr "Unable to retrieve list of volumes."
+
+#: dashboards/project/instances/workflows.py:129
+msgid "Select Volume Snapshot"
+msgstr "Select Volume Snapshot"
+
+#: dashboards/project/instances/workflows.py:138
+msgid "Unable to retrieve list of volume snapshots."
+msgstr "Unable to retrieve list of volume snapshots."
+
+#: dashboards/project/instances/workflows.py:171
+msgid "Instance Source"
+msgstr "Instance Source"
+
+#: dashboards/project/instances/workflows.py:174
+msgid "Instance Snapshot"
+msgstr "Instance Snapshot"
+
+#: dashboards/project/instances/workflows.py:178
+msgid "Size of image to launch."
+msgstr "Size of image to launch."
+
+#: dashboards/project/instances/workflows.py:179
+msgid "Instance Count"
+msgstr "Instance Count"
+
+#: dashboards/project/instances/workflows.py:182
+msgid "Number of instances to launch."
+msgstr "Number of instances to launch."
+
+#: dashboards/project/instances/workflows.py:185
+msgid "Details"
+msgstr "Details"
+
+#: dashboards/project/instances/workflows.py:198
+msgid ""
+"There are no image sources available; you must first create an image before "
+"attempting to launch an instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:203
+msgid "Please select an option for the instance source."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:212
+msgid ""
+"Launching multiple instances is only supported for images and instance "
+"snapshots."
+msgstr ""
+"Launching multiple instances is only supported for images and instance "
+"snapshots."
+
+#: dashboards/project/instances/workflows.py:229
+msgid "Unable to retrieve public images."
+msgstr "Unable to retrieve public images."
+
+#: dashboards/project/instances/workflows.py:244
+msgid "Unable to retrieve images for the current project."
+msgstr "Unable to retrieve images for the current project."
+
+#: dashboards/project/instances/workflows.py:267
+msgid "Select Image"
+msgstr "Select Image"
+
+#: dashboards/project/instances/workflows.py:269
+msgid "No images available."
+msgstr "No images available."
+
+#: dashboards/project/instances/workflows.py:278
+msgid "Select Instance Snapshot"
+msgstr "Select Instance Snapshot"
+
+#: dashboards/project/instances/workflows.py:280
+msgid "No snapshots available."
+msgstr "No snapshots available."
+
+#: dashboards/project/instances/workflows.py:291
+msgid "Unable to retrieve instance flavors."
+msgstr "Unable to retrieve instance flavors."
+
+#: dashboards/project/instances/workflows.py:304 usage/base.py:114
+msgid "Unable to retrieve quota information."
+msgstr "Unable to retrieve quota information."
+
+#: dashboards/project/instances/workflows.py:337
+msgid "Which keypair to use for authentication."
+msgstr "Which keypair to use for authentication."
+
+#: dashboards/project/instances/workflows.py:344
+msgid "Launch instance in these security groups."
+msgstr "Launch instance in these security groups."
+
+#: dashboards/project/instances/workflows.py:349
+msgid ""
+"Control access to your instance via keypairs, security groups, and other "
+"mechanisms."
+msgstr ""
+"Control access to your instance via keypairs, security groups, and other "
+"mechanisms."
+
+#: dashboards/project/instances/workflows.py:359
+msgid "Unable to retrieve keypairs."
+msgstr "Unable to retrieve keypairs."
+
+#: dashboards/project/instances/workflows.py:361
+msgid "Select a keypair"
+msgstr "Select a keypair"
+
+#: dashboards/project/instances/workflows.py:363
+msgid "No keypairs available."
+msgstr "No keypairs available."
+
+#: dashboards/project/instances/workflows.py:372
+msgid "Unable to retrieve list of security groups"
+msgstr "Unable to retrieve list of security groups"
+
+#: dashboards/project/instances/workflows.py:392
+msgid "Customization Script"
+msgstr "Customization Script"
+
+#: dashboards/project/instances/workflows.py:394
+msgid ""
+"A script or set of commands to be executed after the instance has been built "
+"(max 16kb)."
+msgstr ""
+"A script or set of commands to be executed after the instance has been built "
+"(max 16kb)."
+
+#: dashboards/project/instances/workflows.py:401
+msgid "Post-Creation"
+msgstr "Post-Creation"
+
+#: dashboards/project/instances/workflows.py:415
+msgid "Launch instance withthese networks"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:419
+msgid "Networking"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:421
+msgid "Select networks for your instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:433
+msgid "Unable to retrieve networks."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:456
+#, python-format
+msgid "Launched %(count)s named \"%(name)s\"."
+msgstr "Launched %(count)s named \"%(name)s\"."
+
+#: dashboards/project/instances/workflows.py:457
+#, python-format
+msgid "Unable to launch %(count)s named \"%(name)s\"."
+msgstr "Unable to launch %(count)s named \"%(name)s\"."
+
+#: dashboards/project/instances/workflows.py:470
+#, python-format
+msgid "%s instances"
+msgstr "%s instances"
+
+#: dashboards/project/instances/workflows.py:473
+msgid "instance"
+msgstr "instance"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:4
+msgid "Instance Console Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:7
+msgid "Log Length"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:9
+msgid "Go"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:11
+msgid "View Full Log"
+msgstr "View Full Log"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:3
+msgid "Instance Overview"
+msgstr "Instance Overview"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:27
+msgid "VCPU"
+msgstr "VCPU"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:28
+#: usage/tables.py:20
+msgid "Disk"
+msgstr "Disk"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:34
+msgid "IP Addresses"
+msgstr "IP Addresses"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:59
+msgid "No rules defined."
+msgstr "No rules defined."
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:68
+msgid "Meta"
+msgstr "Meta"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:71
+msgid "Key Name"
+msgstr "Key Name"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:84
+msgid "Volumes Attached"
+msgstr "Volumes Attached"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:88
+#: dashboards/project/volumes/tables.py:167
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:38
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:45
+msgid "Attached To"
+msgstr "Attached To"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:90
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:42
+msgid "on"
+msgstr "on"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:94
+msgid "No volumes attached."
+msgstr "No volumes attached."
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:3
+msgid "Instance VNC Console"
+msgstr "Instance VNC Console"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid ""
+"If VNC console is not responding to keyboard input: click the grey status "
+"bar below."
+msgstr ""
+"If VNC console is not responding to keyboard input: click the grey status "
+"bar below."
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid "Click here to show only VNC"
+msgstr "Click here to show only VNC"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:8
+msgid "VNC console is currently unavailabe. Please try again later."
+msgstr "VNC console is currently unavailabe. Please try again later."
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:9
+msgid "Reload"
+msgstr "Reload"
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:2
+msgid ""
+"You can customize your instance after it's launched using the options "
+"available here."
+msgstr ""
+"You can customize your instance after it's launched using the options "
+"available here."
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:3
+msgid ""
+"The \"Customization Script\" field is analogous to \"User Data\" in other "
+"systems."
+msgstr ""
+"The \"Customization Script\" field is analogous to \"User Data\" in other "
+"systems."
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:3
+msgid "Specify the details for launching an instance."
+msgstr "Specify the details for launching an instance."
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:4
+msgid ""
+"The chart below shows the resources used by this project in relation to the "
+"project's quotas."
+msgstr ""
+"The chart below shows the resources used by this project in relation to the "
+"project's quotas."
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:6
+msgid "Flavor Details"
+msgstr "Flavor Details"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+msgid "Total Disk"
+msgstr "Total Disk"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "MB"
+msgstr "MB"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:21
+msgid "Number of Instances"
+msgstr "Number of Instances"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:29
+msgid "Number of VCPUs"
+msgstr "Number of VCPUs"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+#, fuzzy
+msgid "Total RAM"
+msgstr "Total Memory"
+
+#: dashboards/project/instances/templates/instances/_launch_volumes_help.html:3
+msgid ""
+"An instance can be launched with varying types of attached storage. You may "
+"select from those options here."
+msgstr ""
+"An instance can be launched with varying types of attached storage. You may "
+"select from those options here."
+
+#: dashboards/project/instances/templates/instances/_update.html:17
+msgid "You may update the editable properties of your instance here."
+msgstr "You may update the editable properties of your instance here."
+
+#: dashboards/project/instances/templates/instances/detail.html:3
+msgid "Instance Detail"
+msgstr "Instance Detail"
+
+#: dashboards/project/instances/templates/instances/update.html:3
+#: dashboards/project/instances/templates/instances/update.html:6
+msgid "Update Instance"
+msgstr "Update Instance"
+
+#: dashboards/project/networks/tables.py:81
+msgid "Add Subnet"
+msgstr ""
+
+#: dashboards/project/networks/views.py:86
+msgid "Unable to retrieve network details."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:37
+msgid "Network Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:42
+msgid ""
+"From here you can create a new network.\n"
+"In addition a subnet associated with the network can be created in the next "
+"panel."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:56
+msgid "Subnet Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:61
+#: dashboards/project/networks/subnets/forms.py:48
+msgid "Network address in CIDR format (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:67
+msgid "Gateway IP (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:70
+#: dashboards/project/networks/subnets/forms.py:57
+#: dashboards/project/networks/subnets/forms.py:107
+msgid "IP address of Gateway (e.g. 192.168.0.1)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:77
+msgid ""
+"You can create a subnet associated with the new network, in which case "
+"\"Network Address\" must be specified. If you wish to create a network "
+"WITHOUT a subnet, uncheck the \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:89
+msgid "Specify \"Network Address\" or clear \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:94
+#: dashboards/project/networks/subnets/forms.py:70
+msgid "Network Address and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:98
+#: dashboards/project/networks/subnets/forms.py:74
+#: dashboards/project/networks/subnets/forms.py:119
+msgid "Gateway IP and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:112
+msgid "Create"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:113
+#, python-format
+msgid "Created network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:114
+#, python-format
+msgid "Unable to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:130
+#, python-format
+msgid "Network \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:133
+#, python-format
+msgid "Failed to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:152
+#, python-format
+msgid "Subnet \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:155
+#, python-format
+msgid "Failed to create subnet \"%(sub)s\" for network \"%(net)s\"."
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Attached"
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Detached"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:85
+#, python-format
+msgid "Subnet %s was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:90
+#, python-format
+msgid "Failed to create subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:131
+#, python-format
+msgid "Subnet %s was successfully updated."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:136
+#, python-format
+msgid "Failed to update subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/tabs.py:42
+msgid "Unable to retrieve subnet details."
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/_detail_overview.html:3
+msgid "Network Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/detail.html:6
+msgid "Network Detail: "
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:3
+msgid "Port Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:17
+msgid "Fixed IP"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:21
+msgid "IP address:"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:22
+msgid "Subnet ID"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:28
+msgid "Mac Address"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/detail.html:3
+#: dashboards/project/networks/templates/networks/ports/detail.html:6
+msgid "Port Detail"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:3
+msgid "Subnet Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:21
+msgid "IP allocation pool"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:24
+msgid "Start"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:25
+msgid " - End"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/detail.html:3
+#: dashboards/project/networks/templates/networks/subnets/detail.html:6
+msgid "Subnet Detail"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:29
+msgid "Size (GB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:30
+msgid "Use snapshot as a source"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:49
+#, python-format
+msgid "Volume size must be equal to or greater than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:54
+msgid "Unable to load the specified snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:59
+msgid "Choose a snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:83
+#, python-format
+msgid "The volume size cannot be less than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:92
+#, python-format
+msgid ""
+"A volume of %(req)iGB cannot be created as you only have %(avail)iGB of your "
+"quota available."
+msgstr ""
+"A volume of %(req)iGB cannot be created as you only have %(avail)iGB of your "
+"quota available."
+
+#: dashboards/project/volumes/forms.py:99
+msgid "You are already using all of your available volumes."
+msgstr "You are already using all of your available volumes."
+
+#: dashboards/project/volumes/forms.py:115
+msgid "Unable to create volume."
+msgstr "Unable to create volume."
+
+#: dashboards/project/volumes/forms.py:123
+msgid "Attach to Instance"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:124
+msgid "Select an instance to attach to."
+msgstr "Select an instance to attach to."
+
+#: dashboards/project/volumes/forms.py:168
+msgid "Unknown instance (None)"
+msgstr "Unknown instance (None)"
+
+#: dashboards/project/volumes/forms.py:179
+#, python-format
+msgid "Attaching volume %(vol)s to instance %(inst)s on %(dev)s."
+msgstr "Attaching volume %(vol)s to instance %(inst)s on %(dev)s."
+
+#: dashboards/project/volumes/forms.py:188
+msgid "Unable to attach volume."
+msgstr "Unable to attach volume."
+
+#: dashboards/project/volumes/forms.py:212
+#, python-format
+msgid "Creating volume snapshot \"%s\""
+msgstr "Creating volume snapshot \"%s\""
+
+#: dashboards/project/volumes/forms.py:218
+msgid "Unable to create volume snapshot."
+msgstr "Unable to create volume snapshot."
+
+#: dashboards/project/volumes/tables.py:46
+#, fuzzy, python-format
+msgid "Unable to delete volume \"%s\". One or more snapshots depend on it."
+msgstr "Unable to retrieve volume snapshots."
+
+#: dashboards/project/volumes/tables.py:66
+msgid "Edit Attachments"
+msgstr "Edit Attachments"
+
+#: dashboards/project/volumes/tables.py:93
+#, python-format
+msgid "%sGB"
+msgstr "%sGB"
+
+#: dashboards/project/volumes/tables.py:106
+#: dashboards/project/volumes/views.py:149
+msgid "Unable to retrieve attachment information."
+msgstr "Unable to retrieve attachment information."
+
+#: dashboards/project/volumes/tables.py:123
+#, python-format
+msgid "Attached to %(instance)s on %(dev)s"
+msgstr "Attached to %(instance)s on %(dev)s"
+
+#: dashboards/project/volumes/tables.py:180
+msgid "Detach"
+msgstr "Detach"
+
+#: dashboards/project/volumes/tables.py:181
+msgid "Detaching"
+msgstr "Detaching"
+
+#: dashboards/project/volumes/tables.py:216
+#, python-format
+msgid "%(dev)s on instance %(instance_name)s"
+msgstr "%(dev)s on instance %(instance_name)s"
+
+#: dashboards/project/volumes/tabs.py:42
+msgid "Unable to retrieve volume details."
+msgstr "Unable to retrieve volume details."
+
+#: dashboards/project/volumes/views.py:50
+msgid "Unable to retrieve volume list."
+msgstr "Unable to retrieve volume list."
+
+#: dashboards/project/volumes/views.py:58
+msgid "Unable to retrieve volume/instance attachment information"
+msgstr "Unable to retrieve volume/instance attachment information"
+
+#: dashboards/project/volumes/views.py:130
+#: dashboards/project/volumes/views.py:140
+msgid "Unable to retrieve volume information."
+msgstr "Unable to retrieve volume information."
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:9
+#: dashboards/project/volumes/templates/volumes/attach.html:6
+msgid "Manage Volume Attachments"
+msgstr "Manage Volume Attachments"
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:13
+msgid "Attach To Instance"
+msgstr "Attach To Instance"
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:22
+msgid "Attach Volume"
+msgstr "Attach Volume"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:20
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:18
+msgid "Volumes are block devices that can be attached to instances."
+msgstr "Volumes are block devices that can be attached to instances."
+
+#: dashboards/project/volumes/templates/volumes/_create.html:22
+msgid "Volume Quotas"
+msgstr "Volume Quotas"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:25
+msgid "Total Gigabytes"
+msgstr "Total Gigabytes"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:34
+msgid "Number of Volumes"
+msgstr "Number of Volumes"
+
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:8
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:23
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:3
+msgid "Create Volume Snapshot"
+msgstr "Create Volume Snapshot"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:3
+msgid "Volume Overview"
+msgstr "Volume Overview"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:34
+msgid "Attachments"
+msgstr "Attachments"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:46
+msgid "Not attached"
+msgstr "Not attached"
+
+#: dashboards/project/volumes/templates/volumes/create.html:6
+msgid "Create a Volume"
+msgstr "Create a Volume"
+
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:6
+msgid "Create a Volume Snapshot"
+msgstr "Create a Volume Snapshot"
+
+#: dashboards/settings/dashboard.py:24 templates/_header.html:4
+msgid "Settings"
+msgstr "Settings"
+
+#: dashboards/settings/ec2/forms.py:36 dashboards/settings/project/forms.py:36
+msgid "Select a Project"
+msgstr "Select a Project"
+
+#: dashboards/settings/ec2/forms.py:46
+msgid "Unable to retrieve tenant list."
+msgstr "Unable to retrieve tenant list."
+
+#: dashboards/settings/ec2/forms.py:88
+msgid "Unable to fetch EC2 credentials."
+msgstr "Unable to fetch EC2 credentials."
+
+#: dashboards/settings/ec2/forms.py:101
+#, python-format
+msgid "Error writing zipfile: %(exc)s"
+msgstr "Error writing zipfile: %(exc)s"
+
+#: dashboards/settings/ec2/panel.py:25
+msgid "EC2 Credentials"
+msgstr "EC2 Credentials"
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:8
+#: dashboards/settings/ec2/templates/ec2/download_form.html:23
+#: dashboards/settings/ec2/templates/ec2/index.html:3
+#: dashboards/settings/ec2/templates/ec2/index.html:6
+msgid "Download EC2 Credentials"
+msgstr "Download EC2 Credentials"
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:18
+msgid ""
+"Clicking \"Download EC2 Credentials\" will download a zip file which "
+"includes an rc file with your access/secret keys, as well as your x509 "
+"private key and certificate."
+msgstr ""
+"Clicking \"Download EC2 Credentials\" will download a zip file which "
+"includes an rc file with your access/secret keys, as well as your x509 "
+"private key and certificate."
+
+#: dashboards/settings/project/forms.py:71
+#, python-format
+msgid "Error Downloading RC File: %s"
+msgstr "Error Downloading RC File: %s"
+
+#: dashboards/settings/project/panel.py:25
+#: dashboards/settings/project/templates/project/_openrc.html:8
+#: dashboards/settings/project/templates/project/settings.html:3
+#: dashboards/settings/project/templates/project/settings.html:6
+msgid "OpenStack API"
+msgstr "OpenStack API"
+
+#: dashboards/settings/project/tables.py:27
+msgid "Service Name"
+msgstr "Service Name"
+
+#: dashboards/settings/project/tables.py:29
+msgid "Service Endpoint"
+msgstr "Service Endpoint"
+
+#: dashboards/settings/project/tables.py:33
+msgid "API Endpoints"
+msgstr "API Endpoints"
+
+#: dashboards/settings/project/templates/project/_openrc.html:15
+msgid "Download OpenStack RC File"
+msgstr "Download OpenStack RC File"
+
+#: dashboards/settings/project/templates/project/_openrc.html:25
+msgid ""
+"Download the RC file for the selected project, then type \"source openrc\" "
+"in the terminal to configure your environment to communicate with OpenStack."
+msgstr ""
+"Download the RC file for the selected project, then type \"source openrc\" "
+"in the terminal to configure your environment to communicate with OpenStack."
+
+#: dashboards/settings/project/templates/project/_openrc.html:30
+msgid "Download RC File"
+msgstr "Download RC File"
+
+#: dashboards/settings/user/forms.py:57
+msgid "Settings saved."
+msgstr "Settings saved."
+
+#: dashboards/settings/user/panel.py:25
+#: dashboards/settings/user/templates/user/_settings.html:8
+#: dashboards/settings/user/templates/user/settings.html:3
+#: dashboards/settings/user/templates/user/settings.html:6
+msgid "User Settings"
+msgstr "User Settings"
+
+#: dashboards/settings/user/templates/user/_settings.html:18
+msgid "From here you can modify dashboard settings for your user."
+msgstr "From here you can modify dashboard settings for your user."
+
#: templates/403.html:4 templates/403.html.py:9
msgid "Forbidden"
msgstr "Forbidden"
@@ -85,10 +3297,6 @@ msgstr "Forbidden"
msgid "Home"
msgstr "Home"
-#: templates/403.html:24 templates/404.html:23 templates/500.html:23
-msgid "Projects"
-msgstr "Projects"
-
#: templates/404.html:4
msgid "Page Not Found"
msgstr "Page Not Found"
@@ -112,3 +3320,47 @@ msgid ""
msgstr ""
"An unexpected error occurred while processing your request. Please try your "
"request again."
+
+#: templates/_header.html:3
+msgid "Logged in as"
+msgstr ""
+
+#: templates/_header.html:6
+msgid "Help"
+msgstr ""
+
+#: templates/_header.html:8
+msgid "Sign Out"
+msgstr ""
+
+#: test/settings.py:50
+msgid "Password must be between 8 and 18 characters."
+msgstr "Password must be between 8 and 18 characters."
+
+#: usage/base.py:97
+msgid "Unable to retrieve usage information."
+msgstr "Unable to retrieve usage information."
+
+#: usage/base.py:100
+msgid "You are viewing data for the future, which may or may not exist."
+msgstr "You are viewing data for the future, which may or may not exist."
+
+#: usage/tables.py:11
+msgid "Download CSV Summary"
+msgstr "Download CSV Summary"
+
+#: usage/tables.py:25
+msgid "VCPU Hours"
+msgstr "VCPU Hours"
+
+#: usage/tables.py:32
+msgid "Disk GB Hours"
+msgstr "Disk GB Hours"
+
+#: usage/tables.py:40 usage/tables.py:68
+msgid "Usage Summary"
+msgstr "Usage Summary"
+
+#: usage/tables.py:60
+msgid "Uptime"
+msgstr "Uptime"
diff --git a/openstack_dashboard/locale/es/LC_MESSAGES/django.mo b/openstack_dashboard/locale/es/LC_MESSAGES/django.mo
index 775b59372..6a55cba98 100644
--- a/openstack_dashboard/locale/es/LC_MESSAGES/django.mo
+++ b/openstack_dashboard/locale/es/LC_MESSAGES/django.mo
Binary files differ
diff --git a/openstack_dashboard/locale/es/LC_MESSAGES/django.po b/openstack_dashboard/locale/es/LC_MESSAGES/django.po
index 90ffe0f93..005231f12 100644
--- a/openstack_dashboard/locale/es/LC_MESSAGES/django.po
+++ b/openstack_dashboard/locale/es/LC_MESSAGES/django.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Horizon\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-09-18 22:18+0000\n"
+"POT-Creation-Date: 2012-10-05 19:30+0000\n"
"PO-Revision-Date: 2012-08-24 23:27+0000\n"
"Last-Translator: Alberto Molina Coballes <alb.molina@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -19,63 +19,3320 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: settings.py:141
+#: settings.py:142
msgid "Bulgarian (Bulgaria)"
msgstr ""
-#: settings.py:142
+#: settings.py:143
msgid "Czech"
msgstr ""
-#: settings.py:143
+#: settings.py:144
msgid "English"
msgstr "Inglés"
-#: settings.py:144
+#: settings.py:145
msgid "Spanish"
msgstr "Español"
-#: settings.py:145
+#: settings.py:146
msgid "French"
msgstr "Francés"
-#: settings.py:146
+#: settings.py:147
msgid "Italiano"
msgstr "Italiano"
-#: settings.py:147
+#: settings.py:148
msgid "Japanese"
msgstr "Japonés"
-#: settings.py:148
+#: settings.py:149
msgid "Korean (Korea)"
msgstr ""
-#: settings.py:149
+#: settings.py:150
msgid "Dutch (Netherlands)"
msgstr ""
-#: settings.py:150
+#: settings.py:151
msgid "Polish"
msgstr "Polaco"
-#: settings.py:151
+#: settings.py:152
msgid "Portuguese"
msgstr "Portugués"
-#: settings.py:152
+#: settings.py:153
#, fuzzy
msgid "Portuguese (Brazil)"
msgstr "Portugués"
-#: settings.py:153
+#: settings.py:154
msgid "Simplified Chinese"
msgstr "Chino simplificado"
-#: settings.py:154
+#: settings.py:155
msgid "Traditional Chinese"
msgstr "Chino tradicional"
+#: api/keystone.py:56
+#, python-format
+msgid "%(type)s (%(backend)s backend)"
+msgstr "%(type)s (%(backend)s backend)"
+
+#: api/nova.py:191
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(group)s"
+msgstr "PERMITIR %(from)s:%(to)s A %(group)s"
+
+#: api/nova.py:196
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(cidr)s"
+msgstr "PERMITIR %(from)s:%(to)s desde %(cidr)s"
+
+#: api/nova.py:532
+msgid "Unknown instance"
+msgstr "Instancia desconocida"
+
+#: api/swift.py:217
+msgid "Unicode is not currently supported for object copy."
+msgstr "No es posible actualmente utilizar Unicode para copiar objetos "
+
+#: dashboards/admin/dashboard.py:24
+msgid "System Panel"
+msgstr "Panel del Sistema"
+
+#: dashboards/admin/dashboard.py:30
+msgid "Admin"
+msgstr "Admin"
+
+#: dashboards/admin/flavors/forms.py:36 dashboards/admin/networks/forms.py:34
+#: dashboards/admin/networks/forms.py:69
+#: dashboards/admin/networks/ports/forms.py:40
+#: dashboards/admin/networks/ports/forms.py:72
+#: dashboards/admin/networks/ports/tables.py:73
+#: dashboards/admin/networks/subnets/tables.py:70
+#: dashboards/admin/projects/tables.py:87
+#: dashboards/admin/projects/workflows.py:71
+#: dashboards/admin/services/tables.py:38
+#: dashboards/admin/volumes/tables.py:10
+#: dashboards/project/access_and_security/security_groups/forms.py:36
+#: dashboards/project/access_and_security/security_groups/tables.py:58
+#: dashboards/project/images_and_snapshots/images/forms.py:40
+#: dashboards/project/images_and_snapshots/images/forms.py:115
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:9
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:10
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:77
+#: dashboards/project/instances/templates/instances/_detail_overview.html:9
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:9
+#: dashboards/project/networks/forms.py:37
+#: dashboards/project/networks/tables.py:94
+#: dashboards/project/networks/ports/tables.py:40
+#: dashboards/project/networks/subnets/forms.py:43
+#: dashboards/project/networks/subnets/forms.py:102
+#: dashboards/project/networks/subnets/tables.py:82
+#: dashboards/project/networks/templates/networks/_detail_overview.html:7
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:9
+#: dashboards/project/volumes/tables.py:144
+#: dashboards/project/volumes/tables.py:164
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:9
+msgid "Name"
+msgstr "Nombre"
+
+#: dashboards/admin/flavors/forms.py:37 dashboards/admin/flavors/tables.py:41
+#: dashboards/admin/projects/workflows.py:39
+#: dashboards/project/instances/templates/instances/_detail_overview.html:26
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:10
+#: usage/tables.py:19
+msgid "VCPUs"
+msgstr "VCPUs"
+
+#: dashboards/admin/flavors/forms.py:38
+#, fuzzy
+msgid "RAM MB"
+msgstr "RAM (MB)"
+
+#: dashboards/admin/flavors/forms.py:39
+msgid "Root Disk GB"
+msgstr "GB de Disco Raíz"
+
+#: dashboards/admin/flavors/forms.py:40
+msgid "Ephemeral Disk GB"
+msgstr "GB de Disco Efímero"
+
+#: dashboards/admin/flavors/forms.py:50
+msgid "Unable to get unique ID for new flavor."
+msgstr "No ha sido posible obtener un ID único para el nuevo sabor."
+
+#: dashboards/admin/flavors/forms.py:67
+#, python-format
+msgid "Created flavor \"%s\"."
+msgstr "Sabor \"%s\" creado."
+
+#: dashboards/admin/flavors/forms.py:71
+msgid "Unable to create flavor."
+msgstr "No ha sido posible crear el sabor."
+
+#: dashboards/admin/flavors/forms.py:92
+#, python-format
+msgid "Updated flavor \"%s\"."
+msgstr "Se ha actualizado el sabor \"%s\"."
+
+#: dashboards/admin/flavors/forms.py:96
+msgid "Unable to update flavor."
+msgstr "No ha sido posible actualizar el sabor."
+
+#: dashboards/admin/flavors/panel.py:29 dashboards/admin/flavors/tables.py:15
+#: dashboards/admin/flavors/tables.py:52
+#: dashboards/admin/flavors/templates/flavors/index.html:3
+#: dashboards/admin/flavors/templates/flavors/index.html:6
+msgid "Flavors"
+msgstr "Sabores"
+
+#: dashboards/admin/flavors/tables.py:14
+#: dashboards/project/instances/workflows.py:177
+#: dashboards/project/instances/templates/instances/_detail_overview.html:22
+msgid "Flavor"
+msgstr "Sabor"
+
+#: dashboards/admin/flavors/tables.py:23
+#: dashboards/admin/flavors/templates/flavors/_create.html:8
+#: dashboards/admin/flavors/templates/flavors/_create.html:23
+#: dashboards/admin/flavors/templates/flavors/create.html:3
+#: dashboards/admin/flavors/templates/flavors/create.html:6
+msgid "Create Flavor"
+msgstr "Crear sabor"
+
+#: dashboards/admin/flavors/tables.py:30
+#: dashboards/admin/flavors/templates/flavors/_edit.html:8
+#: dashboards/admin/flavors/templates/flavors/edit.html:3
+#: dashboards/admin/flavors/templates/flavors/edit.html:6
+msgid "Edit Flavor"
+msgstr "Editar sabor"
+
+#: dashboards/admin/flavors/tables.py:36
+#, python-format
+msgid "%sMB"
+msgstr "%sMB"
+
+#: dashboards/admin/flavors/tables.py:40
+msgid "Flavor Name"
+msgstr "Nombre del sabor"
+
+#: dashboards/admin/flavors/tables.py:43
+#: dashboards/project/instances/templates/instances/_detail_overview.html:24
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: usage/tables.py:22
+msgid "RAM"
+msgstr "RAM"
+
+#: dashboards/admin/flavors/tables.py:45
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+msgid "Root Disk"
+msgstr "Disco Raíz"
+
+#: dashboards/admin/flavors/tables.py:47
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+msgid "Ephemeral Disk"
+msgstr "Disco Efímero"
+
+#: dashboards/admin/flavors/views.py:49
+msgid "Unable to retrieve flavor list."
+msgstr "No ha sido posible obtener la lista de sabores."
+
+#: dashboards/admin/flavors/views.py:76
+msgid "Unable to retrieve flavor data."
+msgstr "No ha sido posible obtener los datos del sabor."
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:17
+#: dashboards/admin/flavors/templates/flavors/_edit.html:17
+#: dashboards/admin/images/templates/images/_update.html:17
+#: dashboards/admin/networks/templates/networks/_create.html:17
+#: dashboards/admin/networks/templates/networks/ports/_create.html:17
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:17
+#: dashboards/admin/projects/tables.py:89
+#: dashboards/admin/projects/workflows.py:74
+#: dashboards/admin/projects/templates/projects/_add_user.html:17
+#: dashboards/admin/projects/templates/projects/_create.html:17
+#: dashboards/admin/projects/templates/projects/_create_user.html:17
+#: dashboards/admin/projects/templates/projects/_quotas.html:16
+#: dashboards/admin/projects/templates/projects/_update.html:17
+#: dashboards/admin/users/templates/users/_create.html:16
+#: dashboards/admin/users/templates/users/_update.html:16
+#: dashboards/project/access_and_security/security_groups/forms.py:38
+#: dashboards/project/access_and_security/security_groups/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:17
+#: dashboards/project/containers/templates/containers/_copy.html:16
+#: dashboards/project/containers/templates/containers/_create.html:16
+#: dashboards/project/containers/templates/containers/_upload.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/_create.html:16
+#: dashboards/project/networks/templates/networks/subnets/_create.html:17
+#: dashboards/project/volumes/forms.py:28
+#: dashboards/project/volumes/forms.py:195
+#: dashboards/project/volumes/tables.py:147
+#: dashboards/project/volumes/templates/volumes/_create.html:18
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:17
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:14
+msgid "Description"
+msgstr "Descripción"
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:18
+msgid "From here you can define the sizing of a new flavor."
+msgstr "Desde aquí se puede definir el tamaño de uno nuevo sabor."
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:24
+#: dashboards/admin/flavors/templates/flavors/_edit.html:25
+#: dashboards/admin/images/templates/images/_update.html:24
+#: dashboards/admin/networks/templates/networks/_create.html:24
+#: dashboards/admin/networks/templates/networks/_update.html:23
+#: dashboards/admin/networks/templates/networks/ports/_create.html:24
+#: dashboards/admin/networks/templates/networks/ports/_update.html:28
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:24
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:32
+#: dashboards/admin/projects/templates/projects/_add_user.html:24
+#: dashboards/admin/projects/templates/projects/_create.html:24
+#: dashboards/admin/projects/templates/projects/_create_user.html:24
+#: dashboards/admin/projects/templates/projects/_quotas.html:23
+#: dashboards/admin/projects/templates/projects/_update.html:24
+#: dashboards/admin/users/templates/users/_create.html:23
+#: dashboards/admin/users/templates/users/_update.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:32
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:20
+#: dashboards/project/containers/templates/containers/_copy.html:23
+#: dashboards/project/containers/templates/containers/_create.html:23
+#: dashboards/project/containers/templates/containers/_upload.html:24
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:32
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:24
+#: dashboards/project/instances/templates/instances/_update.html:23
+#: dashboards/project/networks/templates/networks/_create.html:23
+#: dashboards/project/networks/templates/networks/_update.html:23
+#: dashboards/project/networks/templates/networks/subnets/_create.html:24
+#: dashboards/project/networks/templates/networks/subnets/_update.html:32
+#: dashboards/project/volumes/templates/volumes/_attach.html:24
+#: dashboards/project/volumes/templates/volumes/_create.html:56
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:24
+#: dashboards/settings/ec2/templates/ec2/download_form.html:24
+#: dashboards/settings/project/templates/project/_openrc.html:31
+#: dashboards/settings/user/templates/user/_settings.html:24
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:18
+msgid "From here you can alter the sizing of the current flavor."
+msgstr "Desde aquí se puede modificar el tamaño del sabor actual."
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:19
+msgid ""
+"Note: this will not affect the resources allocated to any existing instances "
+"using this flavor."
+msgstr ""
+"Nota: esto no afectará a los recursos asociados a ninguna instancia "
+"existente que esté usando este sabor."
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:24
+#: dashboards/admin/projects/workflows.py:270
+#: dashboards/settings/user/templates/user/_settings.html:23
+msgid "Save"
+msgstr "Guardar"
+
+#: dashboards/admin/images/panel.py:29 dashboards/admin/images/tables.py:44
+#: dashboards/admin/images/templates/images/index.html:3
+#: dashboards/admin/images/templates/images/index.html:6
+#: dashboards/project/images_and_snapshots/images/tables.py:47
+#: dashboards/project/images_and_snapshots/images/tables.py:132
+msgid "Images"
+msgstr "Imágenes"
+
+#: dashboards/admin/images/tables.py:40
+#: dashboards/project/images_and_snapshots/images/tables.py:113
+#: dashboards/project/instances/templates/instances/_detail_overview.html:74
+msgid "Image Name"
+msgstr "Nombre de la Imagen"
+
+#: dashboards/admin/images/views.py:55
+msgid "Unable to retrieve image list."
+msgstr "No ha sido posible obtener la lista de imágenes"
+
+#: dashboards/admin/images/templates/images/_update.html:8
+#: dashboards/admin/images/templates/images/_update.html:23
+#: dashboards/admin/images/templates/images/update.html:4
+#: dashboards/admin/images/templates/images/update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:22
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:6
+msgid "Update Image"
+msgstr "Actualizar imagen"
+
+#: dashboards/admin/images/templates/images/_update.html:18
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:17
+msgid "From here you can modify different properties of an image."
+msgstr "Desde aquí es posible modificar diferentes propiedades de una imagen."
+
+#: dashboards/admin/instances/panel.py:29
+#: dashboards/admin/instances/tables.py:94
+#: dashboards/admin/instances/templates/instances/index.html:3
+#: dashboards/admin/projects/workflows.py:40
+#: dashboards/project/instances/panel.py:25
+#: dashboards/project/instances/tables.py:70
+#: dashboards/project/instances/tables.py:90
+#: dashboards/project/instances/tables.py:107
+#: dashboards/project/instances/tables.py:136
+#: dashboards/project/instances/tables.py:313
+#: dashboards/project/instances/templates/instances/index.html:3
+#: dashboards/project/instances/templates/instances/index.html:6
+msgid "Instances"
+msgstr "Instancias"
+
+#: dashboards/admin/instances/tables.py:60 usage/tables.py:30
+msgid "Project Name"
+msgstr "Nombre del Proyecto"
+
+#: dashboards/admin/instances/tables.py:67
+#: dashboards/admin/services/tables.py:40
+msgid "Host"
+msgstr "Anfitrión"
+
+#: dashboards/admin/instances/tables.py:71
+#: dashboards/project/instances/tables.py:290
+#: dashboards/project/instances/workflows.py:176 usage/tables.py:57
+msgid "Instance Name"
+msgstr "Nombre de la Instancia"
+
+#: dashboards/admin/instances/tables.py:72
+#: dashboards/project/access_and_security/floating_ips/tables.py:111
+#: dashboards/project/access_and_security/floating_ips/workflows.py:32
+#: dashboards/project/access_and_security/floating_ips/workflows.py:39
+#: dashboards/project/instances/tables.py:291
+msgid "IP Address"
+msgstr "Dirección IP"
+
+#: dashboards/admin/instances/tables.py:74
+#: dashboards/project/containers/tables.py:256
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:30
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:37
+#: dashboards/project/instances/tables.py:293
+#: dashboards/project/volumes/tables.py:150
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:26
+msgid "Size"
+msgstr "Tamaño"
+
+#: dashboards/admin/instances/tables.py:79
+#: dashboards/admin/networks/tables.py:74
+#: dashboards/admin/networks/ports/tables.py:77
+#: dashboards/project/images_and_snapshots/images/tables.py:119
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:13
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:18
+#: dashboards/project/instances/tables.py:298
+#: dashboards/project/instances/templates/instances/_detail_overview.html:13
+#: dashboards/project/networks/tables.py:100
+#: dashboards/project/networks/ports/tables.py:44
+#: dashboards/project/networks/templates/networks/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:30
+#: dashboards/project/volumes/tables.py:154
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:17
+msgid "Status"
+msgstr "Estado"
+
+#: dashboards/admin/instances/tables.py:83
+#: dashboards/project/instances/tables.py:302
+msgid "Task"
+msgstr "Tarea"
+
+#: dashboards/admin/instances/tables.py:90
+#: dashboards/project/instances/tables.py:309
+msgid "Power State"
+msgstr "Estado"
+
+#: dashboards/admin/instances/views.py:49
+#: dashboards/project/access_and_security/views.py:76
+#: dashboards/project/access_and_security/floating_ips/workflows.py:65
+msgid "Unable to retrieve instance list."
+msgstr "No ha sido posible obtener la lista de instancias"
+
+#: dashboards/admin/instances/views.py:63
+#: dashboards/admin/networks/views.py:48
+msgid "Unable to retrieve instance tenant information."
+msgstr "No ha sido posible obtener la información de la instancia del tenant"
+
+#: dashboards/admin/instances/views.py:80
+#: dashboards/project/instances/views.py:82
+msgid "Unable to retrieve instance size information."
+msgstr "No ha sido posible obtener la información del tamaño de la instancia."
+
+#: dashboards/admin/instances/templates/instances/index.html:6
+msgid "All Instances"
+msgstr "Todas las Instancias"
+
+#: dashboards/admin/networks/forms.py:36
+#: dashboards/admin/networks/tables.py:67
+#: dashboards/admin/projects/tables.py:65 dashboards/project/dashboard.py:40
+#: dashboards/project/instances/workflows.py:38
+msgid "Project"
+msgstr "Proyecto"
+
+#: dashboards/admin/networks/forms.py:37 dashboards/admin/networks/forms.py:74
+#: dashboards/admin/networks/tables.py:72
+#: dashboards/project/networks/tables.py:98
+#: dashboards/project/networks/templates/networks/_detail_overview.html:17
+msgid "Shared"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:46 dashboards/admin/users/forms.py:42
+msgid "Select a project"
+msgstr "Seleccionar un proyecto"
+
+#: dashboards/admin/networks/forms.py:58
+#, python-format
+msgid "Network %s was successfully created."
+msgstr "La red %s se ha creado correctamente."
+
+#: dashboards/admin/networks/forms.py:64
+#, python-format
+msgid "Failed to create network %s"
+msgstr "Ha fallado la creación de la red %s"
+
+#: dashboards/admin/networks/forms.py:71
+#: dashboards/admin/networks/templates/networks/ports/_update.html:12
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:12
+#: dashboards/admin/users/forms.py:114
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:11
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:12
+#: dashboards/project/instances/templates/instances/_detail_overview.html:11
+#: dashboards/project/networks/forms.py:39
+#: dashboards/project/networks/templates/networks/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_update.html:12
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:11
+msgid "ID"
+msgstr "ID"
+
+#: dashboards/admin/networks/forms.py:82
+#: dashboards/project/networks/forms.py:48
+#, python-format
+msgid "Network %s was successfully updated."
+msgstr "La red %s se ha actualizado correctamente."
+
+#: dashboards/admin/networks/forms.py:87
+#: dashboards/project/networks/forms.py:53
+#, python-format
+msgid "Failed to update network %s"
+msgstr "Ha fallado la actualización de la red %s"
+
+#: dashboards/admin/networks/panel.py:25
+#: dashboards/admin/networks/tables.py:35
+#: dashboards/admin/networks/tables.py:80
+#: dashboards/admin/networks/templates/networks/index.html:3
+#: dashboards/admin/networks/templates/networks/index.html:6
+#: dashboards/project/instances/workflows.py:412
+#: dashboards/project/networks/panel.py:25
+#: dashboards/project/networks/tables.py:44
+#: dashboards/project/networks/tables.py:106
+#: dashboards/project/networks/templates/networks/index.html:3
+#: dashboards/project/networks/templates/networks/index.html:6
+msgid "Networks"
+msgstr "Redes"
+
+#: dashboards/admin/networks/tables.py:34
+#: dashboards/project/networks/tables.py:43
+#: dashboards/project/networks/templates/networks/subnets/index.html:3
+#: dashboards/project/networks/templates/networks/subnets/index.html:6
+msgid "Network"
+msgstr "Red"
+
+#: dashboards/admin/networks/tables.py:41
+#: dashboards/project/networks/tables.py:59
+#, python-format
+msgid "Failed to delete network %s"
+msgstr "Ha fallado el borrado de la red %s"
+
+#: dashboards/admin/networks/tables.py:49
+#: dashboards/admin/networks/templates/networks/_create.html:8
+#: dashboards/admin/networks/templates/networks/_create.html:23
+#: dashboards/admin/networks/templates/networks/create.html:3
+#: dashboards/admin/networks/templates/networks/create.html:6
+#: dashboards/project/networks/tables.py:67
+#: dashboards/project/networks/workflows.py:111
+#: dashboards/project/networks/templates/networks/_create.html:7
+#: dashboards/project/networks/templates/networks/_create.html:22
+#: dashboards/project/networks/templates/networks/create.html:3
+#: dashboards/project/networks/templates/networks/create.html:6
+msgid "Create Network"
+msgstr "Crear red"
+
+#: dashboards/admin/networks/tables.py:56
+#: dashboards/admin/networks/templates/networks/_update.html:7
+#: dashboards/project/networks/tables.py:74
+#: dashboards/project/networks/templates/networks/_update.html:7
+msgid "Edit Network"
+msgstr "Editar red"
+
+#: dashboards/admin/networks/tables.py:68
+#: dashboards/admin/networks/ports/forms.py:33
+#: dashboards/project/networks/subnets/forms.py:35
+msgid "Network Name"
+msgstr "Nombre de la red"
+
+#: dashboards/admin/networks/tables.py:71
+#: dashboards/project/networks/tables.py:97
+msgid "Subnets Associated"
+msgstr "Subredes asociadas"
+
+#: dashboards/admin/networks/tables.py:76
+#: dashboards/admin/networks/ports/tables.py:79
+#: dashboards/project/networks/tables.py:102
+#: dashboards/project/networks/ports/tables.py:46
+#: dashboards/project/networks/templates/networks/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:32
+msgid "Admin State"
+msgstr "Estado de Administración"
+
+#: dashboards/admin/networks/views.py:60
+#: dashboards/project/networks/views.py:52
+msgid "Network list can not be retrieved."
+msgstr "No ha sido posible obtener la lista de redes."
+
+#: dashboards/admin/networks/views.py:91
+#: dashboards/project/networks/views.py:109
+msgid "Subnet list can not be retrieved."
+msgstr "No ha sido posible obtener la lista de subredes."
+
+#: dashboards/admin/networks/views.py:103
+#: dashboards/project/networks/views.py:121
+msgid "Port list can not be retrieved."
+msgstr "No ha sido posible obtener la lista de puertos."
+
+#: dashboards/admin/networks/views.py:118
+#: dashboards/project/networks/views.py:134
+#: dashboards/project/networks/subnets/tables.py:96
+#, python-format
+msgid "Unable to retrieve details for network \"%s\"."
+msgstr "No ha sido posible obtener detalles de la red \"%s\"."
+
+#: dashboards/admin/networks/ports/forms.py:36
+#: dashboards/project/networks/subnets/forms.py:39
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:13
+msgid "Network ID"
+msgstr "ID de la red"
+
+#: dashboards/admin/networks/ports/forms.py:42
+#: dashboards/admin/networks/ports/forms.py:74
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:34
+msgid "Device ID"
+msgstr "ID del dispositivo"
+
+#: dashboards/admin/networks/ports/forms.py:54
+#, python-format
+msgid "Port %s was successfully created."
+msgstr "El puerto %s se ha creado correctamente."
+
+#: dashboards/admin/networks/ports/forms.py:59
+#, python-format
+msgid "Failed to create a port for network %s"
+msgstr "Ha fallado la creación de un puerto para la red %s"
+
+#: dashboards/admin/networks/ports/forms.py:84
+#, python-format
+msgid "Port %s was successfully updated."
+msgstr "El puerto %s se ha actualizado correctamente."
+
+#: dashboards/admin/networks/ports/forms.py:89
+#, python-format
+msgid "Failed to update port %s"
+msgstr "Ha fallado la actualización del puerto %s"
+
+#: dashboards/admin/networks/ports/tables.py:34
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:6
+msgid "Port"
+msgstr "Puerto"
+
+#: dashboards/admin/networks/ports/tables.py:35
+#: dashboards/admin/networks/ports/tables.py:83
+#: dashboards/project/networks/ports/tables.py:53
+msgid "Ports"
+msgstr "Puertos"
+
+#: dashboards/admin/networks/ports/tables.py:41
+#: dashboards/admin/networks/subnets/tables.py:39
+#: dashboards/project/networks/subnets/tables.py:51
+#, python-format
+msgid "Failed to delete subnet %s"
+msgstr "Ha fallado el borrado de la subred %s"
+
+#: dashboards/admin/networks/ports/tables.py:51
+#: dashboards/admin/networks/templates/networks/ports/_create.html:8
+#: dashboards/admin/networks/templates/networks/ports/_create.html:23
+#: dashboards/admin/networks/templates/networks/ports/create.html:3
+#: dashboards/admin/networks/templates/networks/ports/create.html:6
+msgid "Create Port"
+msgstr "Crear puerto"
+
+#: dashboards/admin/networks/ports/tables.py:62
+#: dashboards/admin/networks/templates/networks/ports/_update.html:7
+msgid "Edit Port"
+msgstr "Editar puerto"
+
+#: dashboards/admin/networks/ports/tables.py:75
+#: dashboards/project/networks/ports/tables.py:42
+msgid "Fixed IPs"
+msgstr "IPs fijas"
+
+#: dashboards/admin/networks/ports/tables.py:76
+#: dashboards/project/networks/ports/tables.py:43
+msgid "Device Attached"
+msgstr "Dispositivo vinculado"
+
+#: dashboards/admin/networks/ports/tabs.py:32
+#: dashboards/admin/overview/panel.py:29
+#: dashboards/admin/overview/templates/overview/usage.html:6
+#: dashboards/project/images_and_snapshots/images/tabs.py:27
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:27
+#: dashboards/project/instances/tabs.py:26
+#: dashboards/project/networks/ports/tabs.py:32
+#: dashboards/project/networks/subnets/tabs.py:32
+#: dashboards/project/overview/panel.py:29
+#: dashboards/project/overview/templates/overview/usage.html:6
+#: dashboards/project/volumes/tabs.py:27
+msgid "Overview"
+msgstr "Visión General"
+
+#: dashboards/admin/networks/ports/tabs.py:42
+#: dashboards/project/networks/ports/tabs.py:42
+msgid "Unable to retrieve port details."
+msgstr "No ha sido posible obtener los detalles del puerto."
+
+#: dashboards/admin/networks/ports/views.py:49
+#: dashboards/admin/networks/subnets/views.py:49
+#: dashboards/project/networks/subnets/views.py:54
+msgid "Unable to retrieve network."
+msgstr "No ha sido posible obtener la red."
+
+#: dashboards/admin/networks/ports/views.py:82
+msgid "Unable to retrieve port details"
+msgstr "No ha sido posible obtener los detalles del puerto"
+
+#: dashboards/admin/networks/subnets/forms.py:43
+#, python-format
+msgid "Failed to retrieve network %s for a subnet"
+msgstr "No ha sido posible obtener la red %s para una subred"
+
+#: dashboards/admin/networks/subnets/tables.py:32
+#: dashboards/project/networks/subnets/tables.py:44
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:6
+msgid "Subnet"
+msgstr "Subred"
+
+#: dashboards/admin/networks/subnets/tables.py:33
+#: dashboards/admin/networks/subnets/tables.py:81
+#: dashboards/project/networks/subnets/tables.py:45
+#: dashboards/project/networks/subnets/tables.py:104
+msgid "Subnets"
+msgstr "Subredes"
+
+#: dashboards/admin/networks/subnets/tables.py:49
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:8
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:23
+#: dashboards/admin/networks/templates/networks/subnets/create.html:3
+#: dashboards/admin/networks/templates/networks/subnets/create.html:6
+#: dashboards/project/networks/workflows.py:53
+#: dashboards/project/networks/subnets/tables.py:61
+#: dashboards/project/networks/templates/networks/subnets/_create.html:8
+#: dashboards/project/networks/templates/networks/subnets/_create.html:23
+#: dashboards/project/networks/templates/networks/subnets/create.html:3
+#: dashboards/project/networks/templates/networks/subnets/create.html:6
+msgid "Create Subnet"
+msgstr "Crear subred"
+
+#: dashboards/admin/networks/subnets/tables.py:60
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:7
+#: dashboards/project/networks/subnets/tables.py:72
+#: dashboards/project/networks/templates/networks/subnets/_update.html:7
+msgid "Edit Subnet"
+msgstr "Editar Subred"
+
+#: dashboards/admin/networks/subnets/tables.py:72
+#: dashboards/project/access_and_security/security_groups/forms.py:91
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:15
+msgid "CIDR"
+msgstr "CIDR"
+
+#: dashboards/admin/networks/subnets/tables.py:73
+#: dashboards/project/networks/workflows.py:66
+#: dashboards/project/networks/subnets/forms.py:53
+#: dashboards/project/networks/subnets/tables.py:85
+msgid "IP Version"
+msgstr "Versión IP"
+
+#: dashboards/admin/networks/subnets/tables.py:74
+#: dashboards/project/networks/subnets/forms.py:54
+#: dashboards/project/networks/subnets/forms.py:104
+#: dashboards/project/networks/subnets/tables.py:86
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:19
+msgid "Gateway IP"
+msgstr "IP de la puerta de enlace"
+
+#: dashboards/admin/networks/subnets/views.py:82
+#: dashboards/project/networks/subnets/views.py:86
+msgid "Unable to retrieve subnet details"
+msgstr "No ha sido posible obtener los detalles de la subred."
+
+#: dashboards/admin/networks/templates/networks/_create.html:18
+#: dashboards/project/networks/templates/networks/_create.html:17
+msgid "Select a name for your network."
+msgstr "Seleccione un nombre para su red."
+
+#: dashboards/admin/networks/templates/networks/_update.html:16
+#: dashboards/admin/networks/templates/networks/ports/_update.html:21
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:25
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:17
+#: dashboards/project/instances/templates/instances/_update.html:16
+#: dashboards/project/networks/templates/networks/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_update.html:25
+#: dashboards/settings/ec2/templates/ec2/download_form.html:17
+#: dashboards/settings/project/templates/project/_openrc.html:24
+#: dashboards/settings/user/templates/user/_settings.html:17
+msgid "Description:"
+msgstr "Descripción:"
+
+#: dashboards/admin/networks/templates/networks/_update.html:17
+#: dashboards/project/networks/templates/networks/_update.html:17
+msgid "You may update the editable properties of your network here."
+msgstr "Se puede actualizar las propiedades editables de su red aquí."
+
+#: dashboards/admin/networks/templates/networks/_update.html:22
+#: dashboards/admin/networks/templates/networks/ports/_update.html:27
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:31
+#: dashboards/project/instances/templates/instances/_update.html:22
+#: dashboards/project/networks/templates/networks/_update.html:22
+#: dashboards/project/networks/templates/networks/subnets/_update.html:31
+msgid "Save Changes"
+msgstr "Guardar Cambios"
+
+#: dashboards/admin/networks/templates/networks/update.html:3
+#: dashboards/admin/networks/templates/networks/update.html:6
+#: dashboards/project/networks/templates/networks/update.html:3
+#: dashboards/project/networks/templates/networks/update.html:6
+msgid "Update Network"
+msgstr "Actualizar Red"
+
+#: dashboards/admin/networks/templates/networks/ports/_create.html:18
+msgid ""
+"You can create a port for the network. If you specify device ID to be "
+"attached, the device specified will be attached to the port created."
+msgstr ""
+"Se puede crear un puerto para una red. Si se especifica el ID del "
+"dispositivo a vincluar, el dispositivo especificado se vinculará al puerto "
+"creado"
+
+#: dashboards/admin/networks/templates/networks/ports/_update.html:22
+msgid "You may update the editable properties of your port here."
+msgstr "Se puede actualizar las propiedades editables del puerto aquí."
+
+#: dashboards/admin/networks/templates/networks/ports/update.html:3
+#: dashboards/admin/networks/templates/networks/ports/update.html:6
+msgid "Update Port"
+msgstr "Actualizar puerto"
+
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:18
+#: dashboards/project/networks/templates/networks/subnets/_create.html:18
+msgid ""
+"You can create a subnet for the network. Any network address can be "
+"specified unless the network address does not overlap other subnets in the "
+"network."
+msgstr ""
+"Se puede crear una subred para una red. Se puede especificar cualquier "
+"dirección salvo las que solapan con otras subredes de la red."
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:14
+#: dashboards/project/networks/workflows.py:58
+#: dashboards/project/networks/subnets/forms.py:45
+#: dashboards/project/networks/subnets/tables.py:84
+#: dashboards/project/networks/templates/networks/subnets/_update.html:14
+msgid "Network Address"
+msgstr "Direcciones de red"
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:17
+#: dashboards/project/networks/templates/networks/subnets/_update.html:16
+msgid "IP version"
+msgstr "Versión IP"
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:26
+#: dashboards/project/networks/templates/networks/subnets/_update.html:26
+msgid "You may update the editable properties of your subnet here."
+msgstr "Se pueden actualizar las propiedades editables de la subred aquí."
+
+#: dashboards/admin/networks/templates/networks/subnets/index.html:3
+#: dashboards/admin/networks/templates/networks/subnets/index.html:6
+#: dashboards/project/networks/templates/networks/detail.html:3
+msgid "Network Detail"
+msgstr "Detalle de la red"
+
+#: dashboards/admin/networks/templates/networks/subnets/update.html:3
+#: dashboards/admin/networks/templates/networks/subnets/update.html:6
+#: dashboards/project/networks/templates/networks/subnets/update.html:3
+#: dashboards/project/networks/templates/networks/subnets/update.html:6
+msgid "Update Subnet"
+msgstr "Actualizar Subred"
+
+#: dashboards/admin/overview/templates/overview/usage.html:3
+msgid "Usage Overview"
+msgstr "Vistazo General del Uso"
+
+#: dashboards/admin/overview/templates/overview/usage.html:12
+msgid "Monitoring"
+msgstr "Monitorización"
+
+#: dashboards/admin/projects/panel.py:29
+#: dashboards/admin/projects/tables.py:66
+#: dashboards/admin/projects/tables.py:95
+#: dashboards/admin/projects/templates/projects/index.html:8
+#: templates/403.html:24 templates/404.html:23 templates/500.html:23
+msgid "Projects"
+msgstr "Proyectos"
+
+#: dashboards/admin/projects/tables.py:19
+msgid "Modify Users"
+msgstr "Modificar Usuarios"
+
+#: dashboards/admin/projects/tables.py:32
+msgid "View Usage"
+msgstr "Ver utilización"
+
+#: dashboards/admin/projects/tables.py:39
+#: dashboards/admin/projects/templates/projects/_create.html:8
+#: dashboards/admin/projects/templates/projects/_create.html:23
+#: dashboards/admin/projects/templates/projects/create.html:6
+msgid "Create Project"
+msgstr "Crear Proyecto."
+
+#: dashboards/admin/projects/tables.py:46
+#: dashboards/admin/projects/workflows.py:269
+#: dashboards/admin/projects/templates/projects/update.html:3
+#: dashboards/admin/projects/templates/projects/update.html:6
+msgid "Edit Project"
+msgstr "Editar Proyecto"
+
+#: dashboards/admin/projects/tables.py:90
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:60
+#: dashboards/project/networks/templates/networks/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:15
+msgid "Project ID"
+msgstr "ID del proyecto"
+
+#: dashboards/admin/projects/tables.py:91
+#: dashboards/admin/projects/workflows.py:76
+#: dashboards/admin/projects/workflows.py:251
+#: dashboards/admin/services/tables.py:42 dashboards/admin/users/tables.py:40
+#: dashboards/admin/users/tables.py:115
+msgid "Enabled"
+msgstr "Activado"
+
+#: dashboards/admin/projects/tables.py:104
+msgid "Remove"
+msgstr "Borrar"
+
+#: dashboards/admin/projects/tables.py:105
+msgid "Removed"
+msgstr "Borrado"
+
+#: dashboards/admin/projects/tables.py:106 dashboards/admin/users/tables.py:41
+#: dashboards/admin/users/tables.py:75
+#: dashboards/project/instances/workflows.py:39
+msgid "User"
+msgstr "Usuario"
+
+#: dashboards/admin/projects/tables.py:107 dashboards/admin/users/panel.py:29
+#: dashboards/admin/users/tables.py:42 dashboards/admin/users/tables.py:76
+#: dashboards/admin/users/tables.py:122
+#: dashboards/admin/users/templates/users/index.html:8
+msgid "Users"
+msgstr "Usuarios"
+
+#: dashboards/admin/projects/tables.py:125
+msgid "Unable to retrieve role information."
+msgstr "No ha sido posible obtener información del rol."
+
+#: dashboards/admin/projects/tables.py:130
+msgid "Roles"
+msgstr "Roles"
+
+#: dashboards/admin/projects/tables.py:134
+msgid "Users For Project"
+msgstr "Usuarios del Proyecto"
+
+#: dashboards/admin/projects/tables.py:142
+msgid "Add To Project"
+msgstr "Añadir al Proyecto"
+
+#: dashboards/admin/projects/tables.py:154
+msgid "Add New Users"
+msgstr "Añadir Nuevos Usuarios"
+
+#: dashboards/admin/projects/views.py:67
+msgid "Unable to retrieve project information."
+msgstr "No ha sido posible obtener la información del proyecto."
+
+#: dashboards/admin/projects/views.py:87
+msgid "Unable to retrieve project list."
+msgstr "No ha sido posible obtener la lista de proyectos."
+
+#: dashboards/admin/projects/views.py:110
+msgid "Unable to retrieve users."
+msgstr "No ha sido posible obtener los usuarios."
+
+#: dashboards/admin/projects/views.py:154
+msgid "Unable to retrieve default quota values."
+msgstr "No ha sido posible obtener los valores asumidos para las cuotas."
+
+#: dashboards/admin/projects/views.py:182
+msgid "Unable to retrieve project details."
+msgstr "No ha sido posible obtener los detalles del proyecto."
+
+#: dashboards/admin/projects/workflows.py:37
+msgid "Injected File Content Bytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:38
+msgid "Metadata Items"
+msgstr "Ítems de metadatos"
+
+#: dashboards/admin/projects/workflows.py:41
+msgid "Injected Files"
+msgstr "Ficheros inyectados"
+
+#: dashboards/admin/projects/workflows.py:44
+#: dashboards/admin/volumes/panel.py:9 dashboards/admin/volumes/tables.py:15
+#: dashboards/admin/volumes/templates/volumes/index.html:3
+#: dashboards/admin/volumes/templates/volumes/index.html:6
+#: dashboards/project/volumes/panel.py:25
+#: dashboards/project/volumes/tables.py:38
+#: dashboards/project/volumes/tables.py:171
+#: dashboards/project/volumes/tables.py:183
+#: dashboards/project/volumes/templates/volumes/index.html:3
+#: dashboards/project/volumes/templates/volumes/index.html:6
+msgid "Volumes"
+msgstr "Volúmenes"
+
+#: dashboards/admin/projects/workflows.py:45
+msgid "Gigabytes"
+msgstr "Gigabytes"
+
+#: dashboards/admin/projects/workflows.py:46
+msgid "RAM (MB)"
+msgstr "RAM (MB)"
+
+#: dashboards/admin/projects/workflows.py:47
+#: dashboards/project/access_and_security/floating_ips/tables.py:50
+#: dashboards/project/access_and_security/floating_ips/tables.py:128
+msgid "Floating IPs"
+msgstr "IPs flotantes"
+
+#: dashboards/admin/projects/workflows.py:50
+msgid "Quota"
+msgstr "Cuota"
+
+#: dashboards/admin/projects/workflows.py:52
+msgid "From here you can set quotas (max limits) for the project."
+msgstr ""
+"Desde aquí se pueden establecer las cuotas (límites max.) del proyecto."
+
+#: dashboards/admin/projects/workflows.py:81
+#: dashboards/admin/projects/workflows.py:254
+msgid "Project Info"
+msgstr "Info del Proyecto"
+
+#: dashboards/admin/projects/workflows.py:82
+#: dashboards/admin/projects/templates/projects/_create.html:18
+msgid "From here you can create a new project to organize users."
+msgstr "Desde aquí se puede crear un proyecto nuevo para organizar usuarios."
+
+#: dashboards/admin/projects/workflows.py:101
+msgid "Unable to retrieve user list. Please try again later."
+msgstr ""
+"No ha sido posible obtener la lista de usuarios. Por favor inténtelo de "
+"nuevo más tarde."
+
+#: dashboards/admin/projects/workflows.py:155
+#: dashboards/admin/projects/templates/projects/_update_members.html:16
+msgid "Project Members"
+msgstr "Miembros del Proyecto"
+
+#: dashboards/admin/projects/workflows.py:169
+#: dashboards/admin/users/views.py:47
+msgid "Unable to retrieve user list."
+msgstr "No ha sido posible obtener la lista de usuarios."
+
+#: dashboards/admin/projects/workflows.py:180
+msgid "Add Project"
+msgstr "Añadir Proyecto"
+
+#: dashboards/admin/projects/workflows.py:181
+msgid "Finish"
+msgstr "Terminar"
+
+#: dashboards/admin/projects/workflows.py:182
+#, python-format
+msgid "Created new project \"%s\"."
+msgstr "Se ha creado el nuevo proyecto \"%s\"."
+
+#: dashboards/admin/projects/workflows.py:183
+#, python-format
+msgid "Unable to create project \"%s\"."
+msgstr "No ha sido posible crear el proyecto \"%s\"."
+
+#: dashboards/admin/projects/workflows.py:227
+#, python-format
+msgid "Failed to add %s project members and set project quotas."
+msgstr ""
+"Ha fallado al añadir los miembros del proyecto %s y los ajustes de las "
+"cuotas del proyecto."
+
+#: dashboards/admin/projects/workflows.py:246
+msgid "Unable to set project quotas."
+msgstr "No ha sido posible establecer las cuotas para el proyecto."
+
+#: dashboards/admin/projects/workflows.py:256
+msgid "From here you can edit the project details."
+msgstr "Desde aquí se pueden editar los detalles del proyecto."
+
+#: dashboards/admin/projects/workflows.py:271
+#, python-format
+msgid "Modified project \"%s\"."
+msgstr "Proyecto \"%s\" modificado."
+
+#: dashboards/admin/projects/workflows.py:272
+#, python-format
+msgid "Unable to modify project \"%s\"."
+msgstr "No ha sido posible modificar el proyecto \"%s\"."
+
+#: dashboards/admin/projects/workflows.py:342
+#, python-format
+msgid "Failed to modify %s project members and update project quotas."
+msgstr ""
+"Ha fallado la modificación \"%s\" de los miembros del proyecto y "
+"actualización de cuotas."
+
+#: dashboards/admin/projects/workflows.py:363
+msgid ""
+"Modified project information and members, but unable to modify project "
+"quotas."
+msgstr ""
+"Se ha modificado la información del proyecto y sus miembros, pero no ha sido "
+"posible modificar las cuotas del mismo."
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:8
+#: dashboards/admin/projects/templates/projects/add_user.html:3
+#: dashboards/admin/projects/templates/projects/add_user.html:6
+msgid "Add User To Project"
+msgstr "Añadir Usuarios a un Proyecto"
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:18
+msgid "Select the user role for the project."
+msgstr "Seleccione el rol de usuario para el proyecto"
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:23
+msgid "Add"
+msgstr "Añadir"
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:7
+#, python-format
+msgid "Create User for project '%(tenant_name)s'."
+msgstr "Crear usuario para el proyecto '%(tenant_name)s'."
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:18
+msgid "From here you can create a new user to add to this project."
+msgstr "Desde aquí se puede crear un nuevo usuario para añadir al proyecto."
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:23
+#: dashboards/admin/users/tables.py:20
+#: dashboards/admin/users/templates/users/_create.html:7
+#: dashboards/admin/users/templates/users/_create.html:22
+#: dashboards/admin/users/templates/users/create.html:7
+msgid "Create User"
+msgstr "Crear Usuario"
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:7
+#: dashboards/admin/projects/templates/projects/_quotas.html:22
+msgid "Update Quota"
+msgstr "Actualizar Cuota"
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:17
+#, python-format
+msgid ""
+"From here you can edit quotas (max limits) for the project %(tenant.name)s."
+msgstr ""
+"Desde aquí se puede editar las cuotas (límites máx.) del proyecto "
+"%(tenant.name)s."
+
+#: dashboards/admin/projects/templates/projects/_update.html:8
+#: dashboards/admin/projects/templates/projects/_update.html:23
+#: dashboards/admin/projects/templates/projects/quotas.html:6
+msgid "Update Project"
+msgstr "Actualizar Proyecto"
+
+#: dashboards/admin/projects/templates/projects/_update.html:18
+msgid "From here you can edit a project."
+msgstr "Desde aquí se puede editar un proyecto."
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:7
+msgid ""
+"From here you can add and remove members to this project from the list of "
+"all available users."
+msgstr ""
+"Desde aquí se puede añadir y quitar miembros a este proyecto de la lista de "
+"todos los usuarios disponibles."
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:10
+msgid "All Users"
+msgstr "Todos los usuarios"
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:25
+#: dashboards/admin/projects/templates/projects/_update_members.html:32
+msgid "No users found."
+msgstr "No se han encontrado usuarios."
+
+#: dashboards/admin/projects/templates/projects/create_user.html:3
+#: dashboards/admin/projects/templates/projects/create_user.html:6
+msgid "Add New User"
+msgstr "Añadir un nuevo usuario"
+
+#: dashboards/admin/projects/templates/projects/usage.html:3
+msgid "Project Usage Overview"
+msgstr "Vistazo General de la utilización del Proyecto"
+
+#: dashboards/admin/projects/templates/projects/usage.html:7
+msgid "Project Usage"
+msgstr "Utilización del Proyecto"
+
+#: dashboards/admin/projects/templates/projects/users.html:7
+msgid "Users for Project"
+msgstr "Usuarios del Proyecto"
+
+#: dashboards/admin/quotas/panel.py:29 dashboards/admin/quotas/tables.py:36
+msgid "Quotas"
+msgstr "Cuotas"
+
+#: dashboards/admin/quotas/tables.py:28
+msgid "Quota Name"
+msgstr "Nombre de la Cuota"
+
+#: dashboards/admin/quotas/tables.py:29
+msgid "Limit"
+msgstr "Límite"
+
+#: dashboards/admin/quotas/views.py:46
+msgid "Unable to get quota info."
+msgstr "No ha sido posible obtener la info de la cuota."
+
+#: dashboards/admin/quotas/templates/quotas/index.html:8
+msgid "Default Quotas"
+msgstr "Cuotas por defecto"
+
+#: dashboards/admin/services/panel.py:29
+#: dashboards/admin/services/tables.py:47
+#: dashboards/admin/services/templates/services/index.html:8
+msgid "Services"
+msgstr "Servicios"
+
+#: dashboards/admin/services/tables.py:37
+msgid "Id"
+msgstr "Id"
+
+#: dashboards/admin/services/tables.py:39
+msgid "Service"
+msgstr "Servicio"
+
+#: dashboards/admin/users/forms.py:54
+msgid "Passwords do not match."
+msgstr "Las contraseñas no coinciden."
+
+#: dashboards/admin/users/forms.py:62 dashboards/admin/users/forms.py:115
+#: dashboards/admin/users/tables.py:108
+msgid "User Name"
+msgstr "Nombre de Usuario"
+
+#: dashboards/admin/users/forms.py:63 dashboards/admin/users/forms.py:116
+#: dashboards/admin/users/tables.py:109
+msgid "Email"
+msgstr "Email"
+
+#: dashboards/admin/users/forms.py:65 dashboards/admin/users/forms.py:117
+msgid "Password"
+msgstr "Contraseña"
+
+#: dashboards/admin/users/forms.py:70 dashboards/admin/users/forms.py:124
+msgid "Confirm Password"
+msgstr "Confirme contraseña"
+
+#: dashboards/admin/users/forms.py:73 dashboards/admin/users/forms.py:127
+msgid "Primary Project"
+msgstr "Proyecto principal"
+
+#: dashboards/admin/users/forms.py:75
+msgid "Role"
+msgstr "Rol"
+
+#: dashboards/admin/users/forms.py:96
+#, python-format
+msgid "User \"%s\" was successfully created."
+msgstr "El usuario \"%s\" se ha creado correctamente."
+
+#: dashboards/admin/users/forms.py:106
+msgid "Unable to add userto primary project."
+msgstr "No ha sido posible añadir el usuario al proyecto principal."
+
+#: dashboards/admin/users/forms.py:110
+msgid "Unable to create user."
+msgstr "No ha sido posible crear el usuario."
+
+#: dashboards/admin/users/forms.py:151
+msgid "name"
+msgstr "nombre"
+
+#: dashboards/admin/users/forms.py:151
+msgid "email"
+msgstr "email"
+
+#: dashboards/admin/users/forms.py:160
+msgid "primary project"
+msgstr "proyecto principal"
+
+#: dashboards/admin/users/forms.py:173
+#, python-format
+msgid "The user %s has no role defined for"
+msgstr "El usuario %s no tiene un rol definido"
+
+#: dashboards/admin/users/forms.py:181
+msgid "password"
+msgstr "contraseña"
+
+#: dashboards/admin/users/forms.py:190
+msgid "User has been updated successfully."
+msgstr "Se ha actualizado correctamente el usuario."
+
+#: dashboards/admin/users/forms.py:194
+#, python-format
+msgid "Unable to update %(attributes)s for the user."
+msgstr "No ha sido posible obtener %(attributes)s del usuario."
+
+#: dashboards/admin/users/tables.py:32
+#: dashboards/project/images_and_snapshots/images/tables.py:68
+msgid "Edit"
+msgstr "Editar"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Enable"
+msgstr "Habilitado"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Disable"
+msgstr "Deshabilitado"
+
+#: dashboards/admin/users/tables.py:40
+msgid "Disabled"
+msgstr "Deshabilitado"
+
+#: dashboards/admin/users/tables.py:63
+msgid "You cannot disable the user you are currently logged in as."
+msgstr "No puede deshabilitar el usuario que está utilizando actualmente."
+
+#: dashboards/admin/users/tables.py:114
+msgid "User ID"
+msgstr "ID de Usuario"
+
+#: dashboards/admin/users/views.py:70
+msgid "Unable to update user."
+msgstr "No ha sido posible actualizar el usuario."
+
+#: dashboards/admin/users/views.py:104
+msgid "Unable to retrieve user roles."
+msgstr "No ha sido posible obtener los roles de usuario."
+
+#: dashboards/admin/users/templates/users/_create.html:17
+msgid "From here you can create a new user and assign them to a project."
+msgstr "Desde aquí se puede crear un nuevo usuario y asignarlo a un proyecto."
+
+#: dashboards/admin/users/templates/users/_update.html:7
+#: dashboards/admin/users/templates/users/_update.html:22
+#: dashboards/admin/users/templates/users/update.html:7
+msgid "Update User"
+msgstr "Actualizar Usuario"
+
+#: dashboards/admin/users/templates/users/_update.html:17
+msgid ""
+"From here you can edit the user's details, including their default project."
+msgstr ""
+"Desde aquí se puede editar los detalles del usuario, incluido su proyecto "
+"por defecto."
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:3
+#: dashboards/project/volumes/templates/volumes/detail.html:3
+msgid "Volume Details"
+msgstr "Detalles del volumen"
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:6
+#: dashboards/project/volumes/templates/volumes/detail.html:6
+msgid "Volume Detail"
+msgstr "Detalle del volumen"
+
+#: dashboards/project/dashboard.py:24
+msgid "Manage Compute"
+msgstr "Administrar Compute"
+
+#: dashboards/project/dashboard.py:35
+msgid "Object Store"
+msgstr "Almacén de Objetos"
+
+#: dashboards/project/access_and_security/panel.py:26
+#: dashboards/project/instances/workflows.py:348
+msgid "Access & Security"
+msgstr "Acceso y Seguridad"
+
+#: dashboards/project/access_and_security/views.py:51
+msgid "Unable to retrieve keypair list."
+msgstr "No ha sido posible obtener la lista de pares de claves"
+
+#: dashboards/project/access_and_security/views.py:60
+#: dashboards/project/access_and_security/security_groups/views.py:74
+msgid "Unable to retrieve security groups."
+msgstr "No ha sido posible obtener los grupos de seguridad."
+
+#: dashboards/project/access_and_security/views.py:69
+#: dashboards/project/access_and_security/floating_ips/workflows.py:49
+msgid "Unable to retrieve floating IP addresses."
+msgstr "No ha sido posible obtener direcciones IP flotantes."
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:32
+msgid "Pool"
+msgstr "Depósito"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:43
+#, python-format
+msgid "Allocated Floating IP %(ip)s."
+msgstr "IP flotantes %(ip)s asociadas."
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:47
+msgid "Unable to allocate Floating IP."
+msgstr "No es posible asignar IP flotante"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:37
+msgid "Allocate IP To Project"
+msgstr "Asignar una IP a un Proyecto"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:47
+msgid "Release"
+msgstr "Publicación"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:48
+msgid "Released"
+msgstr "Publicado"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:49
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:22
+msgid "Floating IP"
+msgstr "IP flotante"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:6
+#: dashboards/project/instances/tables.py:219
+msgid "Associate Floating IP"
+msgstr "Asociar IP Flotante"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:76
+msgid "Disassociate Floating IP"
+msgstr "Desasociar IP flotante"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:90
+#, python-format
+msgid "Successfully disassociated Floating IP: %s"
+msgstr "IP: %s desasociada correctamente"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:94
+msgid "Unable to disassociate floating IP."
+msgstr "No es posible desasociar IP flotante"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:114
+#: dashboards/project/access_and_security/floating_ips/workflows.py:36
+#: dashboards/project/instances/tables.py:69
+#: dashboards/project/instances/tables.py:89
+#: dashboards/project/instances/tables.py:106
+#: dashboards/project/instances/tables.py:135
+#: dashboards/project/volumes/tables.py:206
+msgid "Instance"
+msgstr "Instancia"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:117
+msgid "Floating IP Pool"
+msgstr "Depósito de IP flotantes"
+
+#: dashboards/project/access_and_security/floating_ips/views.py:65
+msgid "Unable to retrieve floating IP pools."
+msgstr "No ha sido posible obtener los depósitos de IP flotantes."
+
+#: dashboards/project/access_and_security/floating_ips/views.py:68
+msgid "No floating IP pools available."
+msgstr "No hay disponible ningún depósito de IP flotantes"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:40
+msgid "Select the IP address you wish to associate with the selected instance."
+msgstr ""
+"Seleccione la dirección IP que quiere asociar con la instancia seleccionada."
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:53
+msgid "Select an IP address"
+msgstr "Seleccione una dirección IP"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:55
+msgid "No IP addresses available"
+msgstr "No hay direcciones IP disponibles"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:76
+#: dashboards/project/volumes/forms.py:160
+msgid "Select an instance"
+msgstr "Seleccione una instancia"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:78
+#: dashboards/project/volumes/forms.py:162
+msgid "No instances available"
+msgstr "No hay instancias disponibles"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:97
+msgid "Manage Floating IP Associations"
+msgstr "Administrar las asociaciones de IP flotantes"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:98
+msgid "Associate"
+msgstr "Asociar"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:99
+#, python-format
+msgid "IP address %s associated."
+msgstr "Dirección IP %s asociada."
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:100
+#, python-format
+msgid "Unable to associate IP address %s."
+msgstr "No ha sido posible asociar la dirección IP %s."
+
+#: dashboards/project/access_and_security/keypairs/forms.py:38
+#: dashboards/project/access_and_security/keypairs/forms.py:49
+#: dashboards/project/access_and_security/keypairs/tables.py:52
+msgid "Keypair Name"
+msgstr "Nombre del par de claves"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:40
+msgid ""
+"Keypair names may only contain letters, numbers, underscores and hyphens."
+msgstr ""
+"Los pares de claves sólo pueden contener letras, números, guiones bajos y "
+"guiones."
+
+#: dashboards/project/access_and_security/keypairs/forms.py:51
+msgid "Public Key"
+msgstr "Clave pública"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:60
+#, python-format
+msgid "Successfully imported public key: %s"
+msgstr "Se ha importado correctamente la clave pública: %s"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:65
+msgid "Unable to import keypair."
+msgstr "No ha sido posible importar el par de claves."
+
+#: dashboards/project/access_and_security/keypairs/tables.py:30
+#: dashboards/project/instances/tables.py:295
+#: dashboards/project/instances/workflows.py:335
+msgid "Keypair"
+msgstr "Par de claves"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:31
+#: dashboards/project/access_and_security/keypairs/tables.py:60
+msgid "Keypairs"
+msgstr "Pares de claves"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:39
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html:6
+msgid "Import Keypair"
+msgstr "Importar par de claves"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:46
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html:6
+msgid "Create Keypair"
+msgstr "Crear par de claves"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:53
+msgid "Fingerprint"
+msgstr "Huella dactilar"
+
+#: dashboards/project/access_and_security/keypairs/views.py:74
+#, python-format
+msgid "Unable to create keypair: %(exc)s"
+msgstr "No ha sido posible crear el par de claves: %(exc)s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:46
+#, python-format
+msgid "Successfully created security group: %s"
+msgstr "Se ha creado correctamente el grupo de seguridad: %s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:52
+msgid "Unable to create security group."
+msgstr "No ha sido posible crear el grupo de seguridad"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:57
+#: dashboards/project/access_and_security/security_groups/tables.py:93
+msgid "IP Protocol"
+msgstr "Protocolo IP"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:61
+msgid "The protocol which this rule should be applied to."
+msgstr "El protocolo al que debe aplicarse esta regla."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:65
+#: dashboards/project/access_and_security/security_groups/forms.py:71
+#: dashboards/project/access_and_security/security_groups/tables.py:95
+msgid "From Port"
+msgstr "Desde el Puerto"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:66
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP type in the range (-1: 255)"
+msgstr ""
+"TCP/UDP: Introduzca un valor entero entre 1 y 65535. ICMP: introduzca un "
+"valor para el tipo ICMP en el rango (-1: 255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:72
+#: dashboards/project/images_and_snapshots/images/tables.py:115
+msgid "Type"
+msgstr "Tipo"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:74
+#: dashboards/project/access_and_security/security_groups/forms.py:80
+#: dashboards/project/access_and_security/security_groups/tables.py:96
+msgid "To Port"
+msgstr "Al Puerto"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:75
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP code in the range (-1: 255)"
+msgstr ""
+"TCP/UDP: Introduzca un valor entero entre 1 y 65535. ICMP: introduzca un "
+"valor para el código ICMP en el rango (-1: 255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:81
+msgid "Code"
+msgstr "Código"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:84
+msgid "Source Group"
+msgstr "Grupo origen"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:86
+msgid ""
+"To specify an allowed IP range, select CIDR. To allow access from all "
+"members of another security group select Source Group."
+msgstr ""
+"Para especificar un rango de IP permitido, seleccione CIDR. Para permitir "
+"acceso a todos los miembros de otro grupo se seguridad, seleccione Grupo "
+"Origen."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:94
+msgid "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+msgstr "Enrutamiento entre dominios sin clases (p. ej. 192.168.0.0/24)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:121
+msgid "The ICMP type is invalid."
+msgstr "El tipo ICMP no es válido."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:124
+msgid "The ICMP code is invalid."
+msgstr "El código ICMP no es válido."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:127
+msgid "The ICMP type not in range (-1, 255)"
+msgstr "El tipo ICMP está fuera de rango (-1,255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:130
+msgid "The ICMP code not in range (-1, 255)"
+msgstr "El código ICMP está fuera de rango (-1,255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:134
+msgid "The \"from\" port number is invalid."
+msgstr "El número de puerto \"from\" no es válido."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:137
+msgid "The \"to\" port number is invalid."
+msgstr "El número de puerto \"to\" no es válido."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:140
+msgid ""
+"The \"to\" port number must be greater than or equal to the \"from\" port "
+"number."
+msgstr ""
+"El número de puerto \"to\" debe ser mayor o igual que el número de puerto "
+"\"from\"."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:146
+msgid "Either CIDR or Source Group may be specified, but not both."
+msgstr "Se debe especificar el CIDR o el Grupo Origen, pero no ambos."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:168
+#, python-format
+msgid "Successfully added rule: %s"
+msgstr "Se ha añadido correctamente la regla: %s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:173
+msgid "Unable to add rule to security group."
+msgstr "No ha sido posible añadir la regla al grupo de seguridad."
+
+#: dashboards/project/access_and_security/security_groups/tables.py:31
+msgid "Security Group"
+msgstr "Grupo de Seguridad"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:32
+#: dashboards/project/access_and_security/security_groups/tables.py:66
+#: dashboards/project/instances/workflows.py:340
+#: dashboards/project/instances/templates/instances/_detail_overview.html:49
+msgid "Security Groups"
+msgstr "Grupos de Seguridad"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:45
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html:6
+msgid "Create Security Group"
+msgstr "Crear Grupo de Seguridad"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:52
+msgid "Edit Rules"
+msgstr "Editar Reglas"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:72
+msgid "Rule"
+msgstr "Regla"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:73
+msgid "Rules"
+msgstr "Reglas"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:97
+msgid "Source"
+msgstr "Origen"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:107
+msgid "Security Group Rules"
+msgstr "Reglas del Grupo de Seguridad"
+
+#: dashboards/project/access_and_security/security_groups/views.py:60
+msgid "Unable to retrieve security group."
+msgstr "No ha sido posible obtener el grupo de seguridad."
+
+#: dashboards/project/access_and_security/security_groups/views.py:80
+#, python-format
+msgid "%s (current)"
+msgstr "%s (actual)"
+
+#: dashboards/project/access_and_security/templates/access_and_security/index.html:6
+msgid "Access &amp; Security"
+msgstr "Acceso y Seguridad"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:8
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html:3
+msgid "Allocate Floating IP"
+msgstr "Asignar IP Flotante"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:18
+msgid "Allocate a floating IP from a given floating ip pool."
+msgstr "Asociar una IP flotante desde un depósito de ip flotante determinado."
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:20
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:19
+msgid "Project Quotas"
+msgstr "Cuotas de Proyecto"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:31
+msgid "Allocate IP"
+msgstr "Asignar IP"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:17
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:17
+msgid ""
+"Keypairs are ssh credentials which are injected into images when they are "
+"launched. Creating a new key pair registers the public key and downloads the "
+"private key (a .pem file)."
+msgstr ""
+"Los pares de clave son credenciales ssh que se inyectan en las imágenes "
+"cuando se lanzan. Creando un nuevo par de claves, se registra la clave "
+"pública y se descarga la privada (un fichero .pem)"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:18
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:18
+msgid "Protect and use the key as you would any normal ssh private key."
+msgstr "Proteja y use la clave como haría con cualquier clave ssh privada."
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:6
+msgid "Download Keypair"
+msgstr "Descargar Par de claves"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:11
+#, python-format
+msgid ""
+"The keypair &quot;%(keypair_name)s&quot; should download automatically. If "
+"not use the link below."
+msgstr ""
+"El par de claves &quot;%(keypair_name)s&quot; se debe descargar "
+"automáticamente. En caso contrario utilice el enlace siguiente."
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:15
+#, python-format
+msgid "Download keypair &quot;%(keypair_name)s&quot;"
+msgstr "Descargar el par de claves &quot;%(keypair_name)s&quot;"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:18
+msgid "From here you can create a new security group"
+msgstr "Desde aquí se puede crear un nuevo grupo de seguridad"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:9
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html:6
+msgid "Edit Security Group Rules"
+msgstr "Editar las Reglas del Grupo de Seguridad"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:12
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:19
+msgid "Add Rule"
+msgstr "Añadir Regla"
+
+#: dashboards/project/containers/browsers.py:26
+msgid "Swift"
+msgstr "Swift"
+
+#: dashboards/project/containers/browsers.py:29
+#: dashboards/project/containers/tables.py:40
+msgid "Container"
+msgstr "Contenedor"
+
+#: dashboards/project/containers/forms.py:39
+msgid "Slash is not an allowed character."
+msgstr "No se permite el caracter barra (slash)."
+
+#: dashboards/project/containers/forms.py:49
+#: dashboards/project/containers/tables.py:121
+msgid "Container Name"
+msgstr "Número de contenedor"
+
+#: dashboards/project/containers/forms.py:57
+msgid "Container created successfully."
+msgstr "Se ha creado correctamente el Contenedor."
+
+#: dashboards/project/containers/forms.py:68
+msgid "Folder created successfully."
+msgstr "Carpeta creada correctamente."
+
+#: dashboards/project/containers/forms.py:71
+msgid "Unable to create container."
+msgstr "No ha sido posible crear el Contenedor."
+
+#: dashboards/project/containers/forms.py:79
+#: dashboards/project/containers/tables.py:253
+msgid "Object Name"
+msgstr "Nombre del Objeto"
+
+#: dashboards/project/containers/forms.py:81
+msgid "File"
+msgstr "Fichero"
+
+#: dashboards/project/containers/forms.py:95
+msgid "Object was successfully uploaded."
+msgstr "Se ha creado correctamente el objeto."
+
+#: dashboards/project/containers/forms.py:98
+msgid "Unable to upload object."
+msgstr "No ha sido posible subir el objeto."
+
+#: dashboards/project/containers/forms.py:102
+msgid "Destination container"
+msgstr "Contenedor destino"
+
+#: dashboards/project/containers/forms.py:106
+msgid "Destination object name"
+msgstr "Nombre del objeto destino"
+
+#: dashboards/project/containers/forms.py:137
+#: dashboards/project/containers/forms.py:163
+msgid "Unable to copy object."
+msgstr "No ha sido posible copiar el objeto"
+
+#: dashboards/project/containers/forms.py:153
+#, python-format
+msgid "Copied \"%(orig)s\" to \"%(dest)s\" as \"%(new)s\"."
+msgstr "Copiado \"%(orig)s\" a \"%(dest)s\" como \"%(new)s\"."
+
+#: dashboards/project/containers/panel.py:29
+#: dashboards/project/containers/tables.py:41
+#: dashboards/project/containers/tables.py:128
+#: dashboards/project/containers/templates/containers/index.html:7
+msgid "Containers"
+msgstr "Contenedores"
+
+#: dashboards/project/containers/tables.py:62
+#: dashboards/project/containers/templates/containers/_create.html:7
+#: dashboards/project/containers/templates/containers/_create.html:22
+#: dashboards/project/containers/templates/containers/create.html:6
+msgid "Create Container"
+msgstr "Crear Contenedor"
+
+#: dashboards/project/containers/tables.py:69
+msgid "View Container"
+msgstr "Ver Contenedor"
+
+#: dashboards/project/containers/tables.py:81
+#: dashboards/project/containers/templates/containers/_upload.html:23
+#: dashboards/project/containers/templates/containers/upload.html:3
+msgid "Upload Object"
+msgstr "Subir objeto"
+
+#: dashboards/project/containers/tables.py:137
+#: dashboards/project/containers/tables.py:156
+msgid "Object"
+msgstr "Objeto"
+
+#: dashboards/project/containers/tables.py:138
+#: dashboards/project/containers/tables.py:157
+#: dashboards/project/containers/tables.py:263
+msgid "Objects"
+msgstr "Objetos"
+
+#: dashboards/project/containers/tables.py:149
+msgid "Folder"
+msgstr "Carpeta"
+
+#: dashboards/project/containers/tables.py:150
+msgid "Folders"
+msgstr "Carpetas"
+
+#: dashboards/project/containers/tables.py:163
+msgid "Copy"
+msgstr "Copiar"
+
+#: dashboards/project/containers/tables.py:176
+msgid "Download"
+msgstr "Descargar"
+
+#: dashboards/project/containers/tables.py:232
+msgid "Create Folder"
+msgstr "Crear Carpeta"
+
+#: dashboards/project/containers/views.py:53
+msgid "Unable to retrieve container list."
+msgstr "No ha sido posible obtener la lista de contenedores"
+
+#: dashboards/project/containers/views.py:82
+msgid "Unable to retrieve object list."
+msgstr "No ha sido posible obtener la lista de objetos."
+
+#: dashboards/project/containers/views.py:166
+msgid "Unable to retrieve object."
+msgstr "No ha sido posible obtener el objeto"
+
+#: dashboards/project/containers/views.py:200
+msgid "Unable to list containers."
+msgstr "No ha sido posible listar los objetos."
+
+#: dashboards/project/containers/templates/containers/_copy.html:7
+#: dashboards/project/containers/templates/containers/_copy.html:22
+#: dashboards/project/containers/templates/containers/copy.html:3
+#: dashboards/project/containers/templates/containers/copy.html:6
+msgid "Copy Object"
+msgstr "Copiar objeto"
+
+#: dashboards/project/containers/templates/containers/_copy.html:17
+msgid ""
+"Make a new copy of an existing object to store in this or another container. "
+"You may also specify a path at which the new copy should live inside of the "
+"selected container."
+msgstr ""
+"Hacer una copia de un objeto existente para almacenarlo en éste u otro "
+"contenedor. Se puede especificar también la ruta en la que la nueva copia "
+"debe permancer dentro del contenedor seleccionado."
+
+#: dashboards/project/containers/templates/containers/_create.html:17
+msgid ""
+"A container is a storage compartment for your data and provides a way for "
+"you to organize your data. You can think of a container as a folder in "
+"Windows &reg; or a directory in UNIX &reg;. The primary difference between a "
+"container and these other file system concepts is that containers cannot be "
+"nested. You can, however, create an unlimited number of containers within "
+"your account. Data must be stored in a container so you must have at least "
+"one container defined in your account prior to uploading data."
+msgstr ""
+"Un contenedor es un compartimento para almacenamiento de datos y proporciona "
+"una forma de organizarlos. Se puede pensar que un contenedor es como una "
+"carpeta en Windows &reg; o un directorio en UNIX &reg;. La principal "
+"diferencia entre un contenedor y estos otros conceptios de sistemas de "
+"ficheros es que un contenedor no se puede anidar. Sin embargo, sí es posible "
+"crear un número ilimitado de contenedores desde una cuenta. Los datos deben "
+"almacenarse en contenedores, por lo que es necesario tener al menos un "
+"contenedor definido en la cuenta de usuario antes de subir datos."
+
+#: dashboards/project/containers/templates/containers/_upload.html:8
+msgid "Upload Object To Container"
+msgstr "Subir objeto al contenedor"
+
+#: dashboards/project/containers/templates/containers/_upload.html:18
+msgid ""
+"An object is the basic storage entity and any optional metadata that "
+"represents the files you store in the OpenStack Object Storage system. When "
+"you upload data to OpenStack Object Storage, the data is stored as-is (no "
+"compression or encryption) and consists of a location (container), the "
+"object's name, and any metadata consisting of key/value pairs."
+msgstr ""
+"Un objeto es la entidad básica de almacenamiento y opcionalmente metadatos "
+"que representan los ficheros que se almacenan en el Almacén de Objetos de "
+"OpenStack. Cuando se suben datos al Almacén de Objetos de OpenStack, los "
+"datos se almacen tal cual (sin comprimir o cifrar) y están compuestos de una "
+"ubicación (contenedor), el nombre del objeto y metadatos formados por pares "
+"clave/valor."
+
+#: dashboards/project/containers/templates/containers/upload.html:6
+msgid "Upload Objects"
+msgstr "Subir objetos"
+
+#: dashboards/project/images_and_snapshots/panel.py:26
+msgid "Images & Snapshots"
+msgstr "Imágenes e instantáneas"
+
+#: dashboards/project/images_and_snapshots/views.py:63
+msgid "Unable to retrieve images."
+msgstr "No ha sido posible obtener las imágenes."
+
+#: dashboards/project/images_and_snapshots/views.py:74
+msgid "Unable to retrieve snapshots."
+msgstr "No ha sido posible obtener las instantáneas."
+
+#: dashboards/project/images_and_snapshots/views.py:82
+#: dashboards/project/volumes/forms.py:65
+msgid "Unable to retrieve volume snapshots."
+msgstr "No ha sido posible obtener las instantáneas de volúmenes."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:42
+msgid "Image Location"
+msgstr "Ubicación de imágenes"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:43
+msgid "An external (HTTP) URL to load the image from."
+msgstr "Una (HTTP) URL externa desde la que cargar la imagen."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:46
+#: dashboards/project/images_and_snapshots/images/forms.py:130
+#: dashboards/project/images_and_snapshots/images/tables.py:126
+msgid "Format"
+msgstr "Formato"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:50
+msgid "AKI - Amazon Kernel Image"
+msgstr "AKI - Amazon Kernel Image"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:53
+msgid "AMI - Amazon Machine Image"
+msgstr "AMI - Amazon Machine Image"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:56
+msgid "ARI - Amazon Ramdisk Image"
+msgstr "ARI - Amazon Ramdisk Image"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:59
+msgid "ISO - Optical Disk Image"
+msgstr "ISO - Imagen de disco óptico"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:61
+msgid "QCOW2 - QEMU Emulator"
+msgstr "QCOW2 - QEMU Emulator"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:68
+msgid "Minimum Disk (GB)"
+msgstr "Disco Mínimo (GB)"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:69
+#: dashboards/project/images_and_snapshots/images/forms.py:76
+msgid ""
+"The minimum disk size required to boot the image. If unspecified, this value "
+"defaults to 0 (no minimum)."
+msgstr ""
+"El tamaño mínimo de disco es necesario para iniciar la imagen. Si no se "
+"especifica este valor, se asume 0 (sin mínimo)."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:75
+msgid "Minimum Ram (MB)"
+msgstr "RAM Mínima (MB)"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:82
+#: dashboards/project/images_and_snapshots/images/forms.py:134
+#: dashboards/project/images_and_snapshots/images/tables.py:123
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:15
+msgid "Public"
+msgstr "Público"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:106
+#, python-format
+msgid "Your image %s has been queued for creation."
+msgstr "Su imagen %s se ha enviado a la cola para su creación."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:110
+msgid "Unable to create new image."
+msgstr "No ha sido posible crear una imagen nueva."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:116
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:48
+msgid "Kernel ID"
+msgstr "ID del kérnel"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:121
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:52
+msgid "Ramdisk ID"
+msgstr "ID del ramdisk"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:126
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:44
+msgid "Architecture"
+msgstr "Arquitectura"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:138
+#, python-format
+msgid "Unable to update image \"%s\"."
+msgstr "No ha sido posible actualizar la imagen \"%s\"."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:162
+msgid "Image was successfully updated."
+msgstr "La imagen se ha actualizado correctamente."
+
+#: dashboards/project/images_and_snapshots/images/tables.py:34
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:33
+#: dashboards/project/instances/workflows.py:455
+msgid "Launch"
+msgstr "Lanzar"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:46
+#: dashboards/project/images_and_snapshots/images/tables.py:82
+#: dashboards/project/instances/workflows.py:168
+#: dashboards/project/instances/workflows.py:173
+msgid "Image"
+msgstr "Imagen"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:61
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:31
+msgid "Create Image"
+msgstr "Crear Imagen"
+
+#: dashboards/project/images_and_snapshots/images/tabs.py:38
+msgid "Unable to retrieve image details."
+msgstr "No ha sido posible obtener los detalles de la imagen."
+
+#: dashboards/project/images_and_snapshots/images/views.py:61
+msgid "Unable to retrieve image."
+msgstr "No ha sido posible ibtener la imagen."
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:37
+msgid "Instance ID"
+msgstr "ID de instancia"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:40
+#: dashboards/project/volumes/forms.py:193
+msgid "Snapshot Name"
+msgstr "Nombre de la instantánea"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:50
+#, python-format
+msgid "Snapshot \"%(name)s\" created for instance \"%(inst)s\""
+msgstr "Instantánea \"%(name)s\" creada para la instancia \"%(inst)s\""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:56
+msgid "Unable to create snapshot."
+msgstr "No ha sido posible crear la instantánea"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:48
+#: dashboards/project/instances/workflows.py:107
+#: dashboards/project/instances/workflows.py:169
+msgid "Snapshot"
+msgstr "Instantánea"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:49
+msgid "Snapshots"
+msgstr "Instantáneas"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:55
+msgid "Instance Snapshots"
+msgstr "Instantáneas de instancias"
+
+#: dashboards/project/images_and_snapshots/snapshots/views.py:53
+msgid "Unable to retrieve instance."
+msgstr "No ha sido posible obtener la instancia."
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:6
+msgid "Images &amp; Snapshots"
+msgstr "Imágenes e instantáneas"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:6
+msgid "Create An Image"
+msgstr "Crear Una Imagen"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:18
+msgid "Specify an image to upload to the Image Service."
+msgstr "Especifique una imagen para cargar la Servicio de Imágenes."
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:21
+msgid ""
+"Currently only images available via an HTTP URL are supported. The image "
+"location must be accessible to the Image Service. Compressed image binaries "
+"are supported (.zip and .tar.gz.)"
+msgstr ""
+"Actualemtente sólo están soportadas las imágenes a través de una URL HTTP. "
+"La ubicación de la imagen debe ser accesible al Servicios de Imágenes. "
+"Imágenes binarias comprimidas sí están soportadas (.zip and .tar.gz.)"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:24
+msgid "Please note: "
+msgstr "Por favor tenga en cuenta:"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:25
+#, fuzzy
+msgid ""
+"The Image Location field MUST be a valid and direct URL to the image binary. "
+"URLs that redirect or serve error pages will result in unusable images."
+msgstr ""
+"El campo de ubicación de la imagen DEBE ser una URL válida y directa al "
+"binario de la imagen. URLs con redirecciones o páginas de error del servidor "
+"producirán imágenes no utilizables."
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:3
+msgid "Image Overview"
+msgstr "Vistazo general de la imagen"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:6
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:7
+#: dashboards/project/instances/templates/instances/_detail_overview.html:6
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:6
+msgid "Info"
+msgstr "Info"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:17
+msgid "Checksum"
+msgstr "Checksum"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:19
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:39
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:28
+msgid "Created"
+msgstr "Creada"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:21
+msgid "Updated"
+msgstr "Actualizada"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:27
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:34
+#: dashboards/project/instances/templates/instances/_detail_overview.html:19
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:23
+msgid "Specs"
+msgstr "Especificaciones"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:32
+msgid "Container Format"
+msgstr "Formato de contenedor"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:34
+msgid "Disk Format"
+msgstr "Formato de disco"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:40
+msgid "Custom Properties"
+msgstr "Propiedades particulares"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:56
+msgid "Euca2ools state"
+msgstr "Estado Euca2ools"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:64
+msgid "Image Type"
+msgstr "Tipo de imagen"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html:4
+msgid "Image Detail "
+msgstr "Detalle de la imagen"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:8
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:3
+#: dashboards/project/instances/tables.py:179
+#: dashboards/project/volumes/tables.py:76
+msgid "Create Snapshot"
+msgstr "Crear Instantánea"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:18
+msgid "Snapshots preserve the disk state of a running instance."
+msgstr ""
+"Las instantáneas conservan el estado de disco de una instancia en ejecución."
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:20
+#: dashboards/project/instances/workflows.py:75
+#: dashboards/project/instances/workflows.py:110
+#: dashboards/project/instances/templates/instances/_detail_overview.html:93
+#: dashboards/project/volumes/tables.py:37
+#: dashboards/project/volumes/tables.py:182
+msgid "Volume"
+msgstr "Volumen"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:38
+#: dashboards/project/instances/templates/instances/_detail_overview.html:29
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:27
+msgid "GB"
+msgstr "GB"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:6
+msgid "Create a Snapshot"
+msgstr "Crear una instantánea"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:3
+#, fuzzy
+msgid "Volume Snapshot Details"
+msgstr "Instantáneas de volumen"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:6
+#, fuzzy
+msgid "Volume Snapshot Detail"
+msgstr "Instantánea de volumen"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:34
+#: dashboards/project/instances/workflows.py:76
+msgid "Volume Snapshot"
+msgstr "Instantánea de volumen"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:35
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:85
+msgid "Volume Snapshots"
+msgstr "Instantáneas de volumen"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:43
+#: dashboards/project/volumes/tables.py:59
+#: dashboards/project/volumes/templates/volumes/_create.html:8
+#: dashboards/project/volumes/templates/volumes/_create.html:55
+msgid "Create Volume"
+msgstr "Crear Volumen"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:80
+#: dashboards/project/volumes/forms.py:26
+msgid "Volume Name"
+msgstr "Nombre del Volumen"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:41
+#, fuzzy
+msgid "Unable to retrieve snapshot details."
+msgstr "No ha sido posible obtener los detalles del puerto."
+
+#: dashboards/project/instances/forms.py:45
+#, python-format
+msgid "Instance \"%s\" updated."
+msgstr "Instancia \"%s\" actualizada."
+
+#: dashboards/project/instances/forms.py:50
+msgid "Unable to update instance."
+msgstr "No ha sido posible actualizar la instancia."
+
+#: dashboards/project/instances/tables.py:67
+msgid "Terminate"
+msgstr "Terminar"
+
+#: dashboards/project/instances/tables.py:68
+msgid "Scheduled termination of"
+msgstr "Programada la finalización de"
+
+#: dashboards/project/instances/tables.py:87
+msgid "Reboot"
+msgstr "Reiniciar"
+
+#: dashboards/project/instances/tables.py:88
+msgid "Rebooted"
+msgstr "Reiniciada"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Pause"
+msgstr "Pausar"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Unpause"
+msgstr "No pausar"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Paused"
+msgstr "Pausada"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Unpaused"
+msgstr "Unpaused"
+
+#: dashboards/project/instances/tables.py:133
+msgid "Suspend"
+msgstr "Suspender"
+
+#: dashboards/project/instances/tables.py:133
+msgid "Resume"
+msgstr "Reanudar"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Suspended"
+msgstr "Suspendida"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Resumed"
+msgstr "Reanudadas"
+
+#: dashboards/project/instances/tables.py:162
+#: dashboards/project/instances/workflows.py:454
+#: dashboards/project/instances/templates/instances/launch.html:3
+#: dashboards/project/instances/templates/instances/launch.html:6
+msgid "Launch Instance"
+msgstr "Lanzar Instancia"
+
+#: dashboards/project/instances/tables.py:169
+#: dashboards/project/instances/templates/instances/_update.html:7
+msgid "Edit Instance"
+msgstr "Editar Instancia"
+
+#: dashboards/project/instances/tables.py:189
+msgid "VNC Console"
+msgstr "Consola VNC"
+
+#: dashboards/project/instances/tables.py:204
+msgid "View Log"
+msgstr "Ver Log"
+
+#: dashboards/project/instances/tables.py:252
+#, python-format
+msgid "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disk"
+msgstr "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disco"
+
+#: dashboards/project/instances/tables.py:259
+#: dashboards/project/instances/tables.py:266
+msgid "Not available"
+msgstr "No disponible"
+
+#: dashboards/project/instances/tabs.py:36
+msgid "Log"
+msgstr "Log"
+
+#: dashboards/project/instances/tabs.py:48
+#: dashboards/project/instances/views.py:106
+#, python-format
+msgid "Unable to get log for instance \"%s\"."
+msgstr "No ha sido posible obtener el log de la instancia \"%s\"."
+
+#: dashboards/project/instances/tabs.py:55
+msgid "VNC"
+msgstr "VNC"
+
+#: dashboards/project/instances/tabs.py:70
+#: dashboards/project/instances/views.py:122
+#, python-format
+msgid "Unable to get VNC console for instance \"%s\"."
+msgstr "No ha sido posible obtener consola VNC de la instancia \"%s\"."
+
+#: dashboards/project/instances/views.py:59
+msgid "Unable to retrieve instances."
+msgstr "No ha sido posible obtener las instancias."
+
+#: dashboards/project/instances/views.py:144
+msgid "Unable to retrieve instance details."
+msgstr "No ha sido posible obtener los detalles de la instancia."
+
+#: dashboards/project/instances/views.py:179
+#, python-format
+msgid "Unable to retrieve details for instance \"%s\"."
+msgstr "No ha sido posible obtener los detalles de la instancia \"%s\"."
+
+#: dashboards/project/instances/workflows.py:53
+msgid "Project & User"
+msgstr "Proyecto y Usuario"
+
+#: dashboards/project/instances/workflows.py:66
+msgid "Don't boot from a volume."
+msgstr "No iniciar desde un volumen."
+
+#: dashboards/project/instances/workflows.py:67
+msgid "Boot from volume."
+msgstr "Iniciar desde un volumen."
+
+#: dashboards/project/instances/workflows.py:68
+msgid "Boot from volume snapshot (creates a new volume)."
+msgstr "Iniciar desde instantánea de volumen (crea un nuevo volumen)"
+
+#: dashboards/project/instances/workflows.py:72
+#: dashboards/project/instances/workflows.py:90
+msgid "Volume Options"
+msgstr "Opciones de Volumen"
+
+#: dashboards/project/instances/workflows.py:78
+#: dashboards/project/volumes/forms.py:126
+msgid "Device Name"
+msgstr "Nombre del dispositivo"
+
+#: dashboards/project/instances/workflows.py:81
+msgid "Volume mount point (e.g. 'vda' mounts at '/dev/vda')."
+msgstr "Punto de montaje del volumen (p. ej. 'vda' se monta en '/dev/vda')."
+
+#: dashboards/project/instances/workflows.py:83
+msgid "Delete on Terminate"
+msgstr "Borrar al terminar"
+
+#: dashboards/project/instances/workflows.py:86
+msgid "Delete volume on instance terminate"
+msgstr "Borrar volumen al terminar la instancia"
+
+#: dashboards/project/instances/workflows.py:100
+#, python-format
+msgid "Please choose a volume, or select %s."
+msgstr "Por favor, elija un volumen o seleccione %s."
+
+#: dashboards/project/instances/workflows.py:117
+msgid "Select Volume"
+msgstr "Seleccione volumen"
+
+#: dashboards/project/instances/workflows.py:125
+msgid "Unable to retrieve list of volumes."
+msgstr "No ha sido posible obtener la lista de volúmenes."
+
+#: dashboards/project/instances/workflows.py:129
+msgid "Select Volume Snapshot"
+msgstr "Seleccionar Instantánea de Volumen"
+
+#: dashboards/project/instances/workflows.py:138
+msgid "Unable to retrieve list of volume snapshots."
+msgstr "No ha sido posible obtener la lista de instantáneas de volúmenes."
+
+#: dashboards/project/instances/workflows.py:171
+msgid "Instance Source"
+msgstr "Origen de la instancia"
+
+#: dashboards/project/instances/workflows.py:174
+msgid "Instance Snapshot"
+msgstr "Instantánea de la instancia"
+
+#: dashboards/project/instances/workflows.py:178
+msgid "Size of image to launch."
+msgstr "Tamaño de la imagen a lanzar."
+
+#: dashboards/project/instances/workflows.py:179
+msgid "Instance Count"
+msgstr "Total de instancias"
+
+#: dashboards/project/instances/workflows.py:182
+msgid "Number of instances to launch."
+msgstr "Número de instancias a lanzar."
+
+#: dashboards/project/instances/workflows.py:185
+msgid "Details"
+msgstr "Detalles"
+
+#: dashboards/project/instances/workflows.py:198
+msgid ""
+"There are no image sources available; you must first create an image before "
+"attempting to launch an instance."
+msgstr ""
+"No hay imágenes origen disponibles; se debe crear una imagen antes de "
+"intentar lanzar una instancia."
+
+#: dashboards/project/instances/workflows.py:203
+msgid "Please select an option for the instance source."
+msgstr "Por favor seleccione una opción para el origen de la instancia."
+
+#: dashboards/project/instances/workflows.py:212
+msgid ""
+"Launching multiple instances is only supported for images and instance "
+"snapshots."
+msgstr ""
+"El lanzamiento de múltiples instancias sólo está soportado para imágenes y "
+"instantáneas de instancias."
+
+#: dashboards/project/instances/workflows.py:229
+msgid "Unable to retrieve public images."
+msgstr "No ha sido posible obtener las imágenes públicas."
+
+#: dashboards/project/instances/workflows.py:244
+msgid "Unable to retrieve images for the current project."
+msgstr "No ha sido posible obtener imágenes para el proyecto actual."
+
+#: dashboards/project/instances/workflows.py:267
+msgid "Select Image"
+msgstr "Seleccionar Imagen"
+
+#: dashboards/project/instances/workflows.py:269
+msgid "No images available."
+msgstr "No hay imágenes disponibles."
+
+#: dashboards/project/instances/workflows.py:278
+msgid "Select Instance Snapshot"
+msgstr "Seleccionar Instantánea de Instancia"
+
+#: dashboards/project/instances/workflows.py:280
+msgid "No snapshots available."
+msgstr "No hay instantáneas disponibles."
+
+#: dashboards/project/instances/workflows.py:291
+msgid "Unable to retrieve instance flavors."
+msgstr "No ha sido posible obtener los sabores para las instancias"
+
+#: dashboards/project/instances/workflows.py:304 usage/base.py:114
+msgid "Unable to retrieve quota information."
+msgstr "No ha sido posible obtener información de las cuotas."
+
+#: dashboards/project/instances/workflows.py:337
+msgid "Which keypair to use for authentication."
+msgstr "Qué par de claves utilizar para la autenticación."
+
+#: dashboards/project/instances/workflows.py:344
+msgid "Launch instance in these security groups."
+msgstr "Lanzar instancias en estos grupos de seguridad."
+
+#: dashboards/project/instances/workflows.py:349
+msgid ""
+"Control access to your instance via keypairs, security groups, and other "
+"mechanisms."
+msgstr ""
+"Controlar el acceso a sus instancias mediante pares de claves, grupos de "
+"seguridad y otros mecanismos."
+
+#: dashboards/project/instances/workflows.py:359
+msgid "Unable to retrieve keypairs."
+msgstr "No ha sido posible obtener los pares de claves."
+
+#: dashboards/project/instances/workflows.py:361
+msgid "Select a keypair"
+msgstr "Seleccione un par de claves"
+
+#: dashboards/project/instances/workflows.py:363
+msgid "No keypairs available."
+msgstr "No hay pares de claves disponibles."
+
+#: dashboards/project/instances/workflows.py:372
+msgid "Unable to retrieve list of security groups"
+msgstr "No ha sido posible obtener la lista de los grupos de seguridad"
+
+#: dashboards/project/instances/workflows.py:392
+msgid "Customization Script"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:394
+msgid ""
+"A script or set of commands to be executed after the instance has been built "
+"(max 16kb)."
+msgstr ""
+"Un script o un conjunto de instrucciones para ejecutar una vez que la "
+"instancia se haya levantado (max 16kb)."
+
+#: dashboards/project/instances/workflows.py:401
+msgid "Post-Creation"
+msgstr "Post-creación"
+
+#: dashboards/project/instances/workflows.py:415
+msgid "Launch instance withthese networks"
+msgstr "Lanzar la instancia con estas redes"
+
+#: dashboards/project/instances/workflows.py:419
+msgid "Networking"
+msgstr "Interconexiones"
+
+#: dashboards/project/instances/workflows.py:421
+msgid "Select networks for your instance."
+msgstr "Seleccione redes para su instancia."
+
+#: dashboards/project/instances/workflows.py:433
+msgid "Unable to retrieve networks."
+msgstr "No ha sido posible obtener las redes."
+
+#: dashboards/project/instances/workflows.py:456
+#, python-format
+msgid "Launched %(count)s named \"%(name)s\"."
+msgstr "Lanzadas %(count)s de nombre \"%(name)s\"."
+
+#: dashboards/project/instances/workflows.py:457
+#, python-format
+msgid "Unable to launch %(count)s named \"%(name)s\"."
+msgstr "No ha sido posible lanzar %(count)s de nombre \"%(name)s\"."
+
+#: dashboards/project/instances/workflows.py:470
+#, python-format
+msgid "%s instances"
+msgstr "%s instancias"
+
+#: dashboards/project/instances/workflows.py:473
+msgid "instance"
+msgstr "instancia"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:4
+msgid "Instance Console Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:7
+msgid "Log Length"
+msgstr "Longitud del Log"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:9
+msgid "Go"
+msgstr "Ir"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:11
+msgid "View Full Log"
+msgstr "Ver el log completo"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:3
+msgid "Instance Overview"
+msgstr "Visión general de la instancia"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:27
+msgid "VCPU"
+msgstr "VCPU"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:28
+#: usage/tables.py:20
+msgid "Disk"
+msgstr "Disco"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:34
+msgid "IP Addresses"
+msgstr "Direcciones IP"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:59
+msgid "No rules defined."
+msgstr "No hay reglas definidas."
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:68
+msgid "Meta"
+msgstr "Meta"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:71
+msgid "Key Name"
+msgstr "Nombre del par de claves"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:84
+msgid "Volumes Attached"
+msgstr "Volúmenes vinculados"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:88
+#: dashboards/project/volumes/tables.py:167
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:38
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:45
+msgid "Attached To"
+msgstr "Vinculado a"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:90
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:42
+msgid "on"
+msgstr "en"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:94
+msgid "No volumes attached."
+msgstr "No hay volúmenes vinculados."
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:3
+msgid "Instance VNC Console"
+msgstr "Consola VNC de la instancia"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid ""
+"If VNC console is not responding to keyboard input: click the grey status "
+"bar below."
+msgstr ""
+"Si la consola VNC no responde al teclado: haga click en la barra gris "
+"inferior."
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid "Click here to show only VNC"
+msgstr "Haga click aquí para mostrar sólo VNC"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:8
+msgid "VNC console is currently unavailabe. Please try again later."
+msgstr ""
+"No está disponible la consola VNC actualmente. Por favor inténtelo de nuevo "
+"más tarde."
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:9
+msgid "Reload"
+msgstr "Recargar"
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:2
+msgid ""
+"You can customize your instance after it's launched using the options "
+"available here."
+msgstr ""
+"Se pueden personalizar instancias después de lanzarlas utilizando las "
+"opciones disponibles aquí."
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:3
+msgid ""
+"The \"Customization Script\" field is analogous to \"User Data\" in other "
+"systems."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:3
+msgid "Specify the details for launching an instance."
+msgstr "Especificar los detalles para lanzar una instancia."
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:4
+msgid ""
+"The chart below shows the resources used by this project in relation to the "
+"project's quotas."
+msgstr ""
+"El siguiente gráfico muestra los recursos utilizados por este proyecto en "
+"relación a las cuotas del proyecto."
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:6
+msgid "Flavor Details"
+msgstr "Detalles del Sabor"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+msgid "Total Disk"
+msgstr "Disco Total"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "MB"
+msgstr "MB"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:21
+msgid "Number of Instances"
+msgstr "Número de Instancias"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:29
+msgid "Number of VCPUs"
+msgstr "Número de VCPUs"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+#, fuzzy
+msgid "Total RAM"
+msgstr "Memoria total"
+
+#: dashboards/project/instances/templates/instances/_launch_volumes_help.html:3
+msgid ""
+"An instance can be launched with varying types of attached storage. You may "
+"select from those options here."
+msgstr ""
+"Una instancia se puede lanzar con varios tipos de volúmenes vinculados, que "
+"se pueden seleccionar aquí."
+
+#: dashboards/project/instances/templates/instances/_update.html:17
+msgid "You may update the editable properties of your instance here."
+msgstr "Se puede actualizar las propiedades editables de la instancia aquí."
+
+#: dashboards/project/instances/templates/instances/detail.html:3
+msgid "Instance Detail"
+msgstr "Detalle de la instancia"
+
+#: dashboards/project/instances/templates/instances/update.html:3
+#: dashboards/project/instances/templates/instances/update.html:6
+msgid "Update Instance"
+msgstr "Actualizar instancia"
+
+#: dashboards/project/networks/tables.py:81
+msgid "Add Subnet"
+msgstr "Añadir Subred"
+
+#: dashboards/project/networks/views.py:86
+msgid "Unable to retrieve network details."
+msgstr "No ha sido posible obtener los detalles de la red."
+
+#: dashboards/project/networks/workflows.py:37
+msgid "Network Name (optional)"
+msgstr "Nombre de la red (opcional)"
+
+#: dashboards/project/networks/workflows.py:42
+msgid ""
+"From here you can create a new network.\n"
+"In addition a subnet associated with the network can be created in the next "
+"panel."
+msgstr ""
+"Desde aquí se puede creat una nueva red. ⏎ Adicionalmente una subred "
+"asociada a esta red se creará en el siguiente panel."
+
+#: dashboards/project/networks/workflows.py:56
+msgid "Subnet Name (optional)"
+msgstr "Nombre de subred (opcional)"
+
+#: dashboards/project/networks/workflows.py:61
+#: dashboards/project/networks/subnets/forms.py:48
+msgid "Network address in CIDR format (e.g. 192.168.0.0/24)"
+msgstr "Dirección de red en formato CIDR (p. ej. 192.168.0.0/24)"
+
+#: dashboards/project/networks/workflows.py:67
+msgid "Gateway IP (optional)"
+msgstr "IP de la puerta de enlace (opcional)"
+
+#: dashboards/project/networks/workflows.py:70
+#: dashboards/project/networks/subnets/forms.py:57
+#: dashboards/project/networks/subnets/forms.py:107
+msgid "IP address of Gateway (e.g. 192.168.0.1)"
+msgstr "IP de la puerta de enlace (p. ej. 192.168.0.1)"
+
+#: dashboards/project/networks/workflows.py:77
+msgid ""
+"You can create a subnet associated with the new network, in which case "
+"\"Network Address\" must be specified. If you wish to create a network "
+"WITHOUT a subnet, uncheck the \"Create Subnet\" checkbox."
+msgstr ""
+"Se puede crear una subred asociada con la nueva red, en cuyo caso se debe "
+"especificar \"Dirección de red\". Si se quiere crear una nueva red SIN una "
+"subred, desactive el cuadro \"Crear Subred\"."
+
+#: dashboards/project/networks/workflows.py:89
+msgid "Specify \"Network Address\" or clear \"Create Subnet\" checkbox."
+msgstr ""
+"Especifique una \"Dirección de red\" o desactive el cuadro \"Crear Subred\"."
+
+#: dashboards/project/networks/workflows.py:94
+#: dashboards/project/networks/subnets/forms.py:70
+msgid "Network Address and IP version are inconsistent."
+msgstr "La dirección de red y la versión IP son inconsistentes."
+
+#: dashboards/project/networks/workflows.py:98
+#: dashboards/project/networks/subnets/forms.py:74
+#: dashboards/project/networks/subnets/forms.py:119
+msgid "Gateway IP and IP version are inconsistent."
+msgstr ""
+"La dirección IP de la puerta de enlace y la versión IP son inconsistentes."
+
+#: dashboards/project/networks/workflows.py:112
+msgid "Create"
+msgstr "Crear"
+
+#: dashboards/project/networks/workflows.py:113
+#, python-format
+msgid "Created network \"%s\"."
+msgstr "Se ha creado la red \"%s\"."
+
+#: dashboards/project/networks/workflows.py:114
+#, python-format
+msgid "Unable to create network \"%s\"."
+msgstr "No ha sido posible crear la red \"%s\"."
+
+#: dashboards/project/networks/workflows.py:130
+#, python-format
+msgid "Network \"%s\" was successfully created."
+msgstr "La red \"%s\" se ha creado correctamente."
+
+#: dashboards/project/networks/workflows.py:133
+#, python-format
+msgid "Failed to create network \"%s\"."
+msgstr "Ha fallado la creación de la red \"%s\"."
+
+#: dashboards/project/networks/workflows.py:152
+#, python-format
+msgid "Subnet \"%s\" was successfully created."
+msgstr "La subred \"%s\" se ha creado correctamente."
+
+#: dashboards/project/networks/workflows.py:155
+#, python-format
+msgid "Failed to create subnet \"%(sub)s\" for network \"%(net)s\"."
+msgstr "Ha fallado la creación de la subred \"%(sub)s\" de la red \"%(net)s\"."
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Attached"
+msgstr "Vinculado"
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Detached"
+msgstr "Desvinculado"
+
+#: dashboards/project/networks/subnets/forms.py:85
+#, python-format
+msgid "Subnet %s was successfully created."
+msgstr "La subred %s se ha creado correctamente."
+
+#: dashboards/project/networks/subnets/forms.py:90
+#, python-format
+msgid "Failed to create subnet %s"
+msgstr "Ha fallado la creación de la subred %s"
+
+#: dashboards/project/networks/subnets/forms.py:131
+#, python-format
+msgid "Subnet %s was successfully updated."
+msgstr "La subred %s se ha actualizado correctamente."
+
+#: dashboards/project/networks/subnets/forms.py:136
+#, python-format
+msgid "Failed to update subnet %s"
+msgstr "Ha fallado la actualización de la subred %s"
+
+#: dashboards/project/networks/subnets/tabs.py:42
+msgid "Unable to retrieve subnet details."
+msgstr "No ha sido posible obtener los detalles de la subred."
+
+#: dashboards/project/networks/templates/networks/_detail_overview.html:3
+msgid "Network Overview"
+msgstr "Vistazo General de la red"
+
+#: dashboards/project/networks/templates/networks/detail.html:6
+msgid "Network Detail: "
+msgstr "Detalle de la red:"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:3
+msgid "Port Overview"
+msgstr "Vistazo General del puerto"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:17
+msgid "Fixed IP"
+msgstr "IP fija"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:21
+msgid "IP address:"
+msgstr "Dirección IP:"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:22
+msgid "Subnet ID"
+msgstr "ID Subred"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:28
+msgid "Mac Address"
+msgstr "Dirección Mac"
+
+#: dashboards/project/networks/templates/networks/ports/detail.html:3
+#: dashboards/project/networks/templates/networks/ports/detail.html:6
+msgid "Port Detail"
+msgstr "Detalle del puerto"
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:3
+msgid "Subnet Overview"
+msgstr "Vistazo General de la subred"
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:21
+msgid "IP allocation pool"
+msgstr "Depósito de IP para asociar"
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:24
+msgid "Start"
+msgstr "Empezar"
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:25
+msgid " - End"
+msgstr "- Terminar"
+
+#: dashboards/project/networks/templates/networks/subnets/detail.html:3
+#: dashboards/project/networks/templates/networks/subnets/detail.html:6
+msgid "Subnet Detail"
+msgstr "Detalle de la subred"
+
+#: dashboards/project/volumes/forms.py:29
+msgid "Size (GB)"
+msgstr "Tamaño (GB)"
+
+#: dashboards/project/volumes/forms.py:30
+msgid "Use snapshot as a source"
+msgstr "Usar una instantánea como origen"
+
+#: dashboards/project/volumes/forms.py:49
+#, python-format
+msgid "Volume size must be equal to or greater than the snapshot size (%sGB)"
+msgstr ""
+"El tamaño del volumen debe ser igual o mayor que el tamaño de la instantánea "
+"(%s GB)"
+
+#: dashboards/project/volumes/forms.py:54
+msgid "Unable to load the specified snapshot."
+msgstr "No ha sido posible cargar la instantánea especificada."
+
+#: dashboards/project/volumes/forms.py:59
+msgid "Choose a snapshot"
+msgstr "Eliga una instantánea"
+
+#: dashboards/project/volumes/forms.py:83
+#, python-format
+msgid "The volume size cannot be less than the snapshot size (%sGB)"
+msgstr ""
+"El tamaño del volumen no puede ser menor que el de la instantánea (%sGB)"
+
+#: dashboards/project/volumes/forms.py:92
+#, python-format
+msgid ""
+"A volume of %(req)iGB cannot be created as you only have %(avail)iGB of your "
+"quota available."
+msgstr ""
+"Un volumen de %(req)iGB no se puede crear, ya que sólo tiene %(avail)iGB de "
+"cuota disponible."
+
+#: dashboards/project/volumes/forms.py:99
+msgid "You are already using all of your available volumes."
+msgstr "Actualmente está utilizando todos sus volúmenes disponibles."
+
+#: dashboards/project/volumes/forms.py:115
+msgid "Unable to create volume."
+msgstr "No ha sido posible crear el volumen."
+
+#: dashboards/project/volumes/forms.py:123
+msgid "Attach to Instance"
+msgstr "Vincular a Instancia"
+
+#: dashboards/project/volumes/forms.py:124
+msgid "Select an instance to attach to."
+msgstr "Seleccione una instancia a la que vincular."
+
+#: dashboards/project/volumes/forms.py:168
+msgid "Unknown instance (None)"
+msgstr "Instancia desconocida (None)"
+
+#: dashboards/project/volumes/forms.py:179
+#, python-format
+msgid "Attaching volume %(vol)s to instance %(inst)s on %(dev)s."
+msgstr "Vinculando el volumen %(vol)s a la instancia %(inst)s en %(dev)s."
+
+#: dashboards/project/volumes/forms.py:188
+msgid "Unable to attach volume."
+msgstr "No ha sido posible vincular el volumen."
+
+#: dashboards/project/volumes/forms.py:212
+#, python-format
+msgid "Creating volume snapshot \"%s\""
+msgstr "Creando la instantánea del volumen \"%s\""
+
+#: dashboards/project/volumes/forms.py:218
+msgid "Unable to create volume snapshot."
+msgstr "No ha sido posible crear la instantánea del volumen."
+
+#: dashboards/project/volumes/tables.py:46
+#, fuzzy, python-format
+msgid "Unable to delete volume \"%s\". One or more snapshots depend on it."
+msgstr "No ha sido posible obtener las instantáneas de volúmenes."
+
+#: dashboards/project/volumes/tables.py:66
+msgid "Edit Attachments"
+msgstr "Editar Vínculos"
+
+#: dashboards/project/volumes/tables.py:93
+#, python-format
+msgid "%sGB"
+msgstr "%sGB"
+
+#: dashboards/project/volumes/tables.py:106
+#: dashboards/project/volumes/views.py:149
+msgid "Unable to retrieve attachment information."
+msgstr "No ha sido posible obtener la información del vínculo."
+
+#: dashboards/project/volumes/tables.py:123
+#, python-format
+msgid "Attached to %(instance)s on %(dev)s"
+msgstr "Vinculada a %(instance)s en %(dev)s"
+
+#: dashboards/project/volumes/tables.py:180
+msgid "Detach"
+msgstr "Separar"
+
+#: dashboards/project/volumes/tables.py:181
+msgid "Detaching"
+msgstr "Desvinculando"
+
+#: dashboards/project/volumes/tables.py:216
+#, python-format
+msgid "%(dev)s on instance %(instance_name)s"
+msgstr "%(dev)s en instancia %(instance_name)s"
+
+#: dashboards/project/volumes/tabs.py:42
+msgid "Unable to retrieve volume details."
+msgstr "No ha sido posible obtener detalles del volumen."
+
+#: dashboards/project/volumes/views.py:50
+msgid "Unable to retrieve volume list."
+msgstr "No ha sido posible obtener la lista de volúmenes."
+
+#: dashboards/project/volumes/views.py:58
+msgid "Unable to retrieve volume/instance attachment information"
+msgstr ""
+"No ha sido posible obtener la información de vinculación volumen/instancia"
+
+#: dashboards/project/volumes/views.py:130
+#: dashboards/project/volumes/views.py:140
+msgid "Unable to retrieve volume information."
+msgstr "No ha sido posible obtener información del volumen."
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:9
+#: dashboards/project/volumes/templates/volumes/attach.html:6
+msgid "Manage Volume Attachments"
+msgstr "Administrar vínculos de volúmenes"
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:13
+msgid "Attach To Instance"
+msgstr "Vincular a una Instancia"
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:22
+msgid "Attach Volume"
+msgstr "Vincular volumen"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:20
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:18
+msgid "Volumes are block devices that can be attached to instances."
+msgstr ""
+"Los volúmenes son dispositivos de bloques que se pueden vincular a "
+"instancias."
+
+#: dashboards/project/volumes/templates/volumes/_create.html:22
+msgid "Volume Quotas"
+msgstr "Cuotas de volúmen"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:25
+msgid "Total Gigabytes"
+msgstr "Total Gigabytes"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:34
+msgid "Number of Volumes"
+msgstr "Número de Volúmenes"
+
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:8
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:23
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:3
+msgid "Create Volume Snapshot"
+msgstr "Crear una instantánea de un volumen"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:3
+msgid "Volume Overview"
+msgstr "Vista general del volumen"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:34
+msgid "Attachments"
+msgstr "Anexos"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:46
+msgid "Not attached"
+msgstr "No vinculado"
+
+#: dashboards/project/volumes/templates/volumes/create.html:6
+msgid "Create a Volume"
+msgstr "Crear un volumen"
+
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:6
+msgid "Create a Volume Snapshot"
+msgstr "Crear una instantánea de un volumen"
+
+#: dashboards/settings/dashboard.py:24 templates/_header.html:4
+msgid "Settings"
+msgstr "Ajustes"
+
+#: dashboards/settings/ec2/forms.py:36 dashboards/settings/project/forms.py:36
+msgid "Select a Project"
+msgstr "Seleccione un Proyecto"
+
+#: dashboards/settings/ec2/forms.py:46
+msgid "Unable to retrieve tenant list."
+msgstr "No ha sido posible obtener la lista de tenants"
+
+#: dashboards/settings/ec2/forms.py:88
+msgid "Unable to fetch EC2 credentials."
+msgstr "No ha sido posible obtener las credenciales EC2."
+
+#: dashboards/settings/ec2/forms.py:101
+#, python-format
+msgid "Error writing zipfile: %(exc)s"
+msgstr "Error al escribir el fichero zip: %(exc)s"
+
+#: dashboards/settings/ec2/panel.py:25
+msgid "EC2 Credentials"
+msgstr "Credenciales EC2"
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:8
+#: dashboards/settings/ec2/templates/ec2/download_form.html:23
+#: dashboards/settings/ec2/templates/ec2/index.html:3
+#: dashboards/settings/ec2/templates/ec2/index.html:6
+msgid "Download EC2 Credentials"
+msgstr "Descargar las credenciales EC2"
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:18
+msgid ""
+"Clicking \"Download EC2 Credentials\" will download a zip file which "
+"includes an rc file with your access/secret keys, as well as your x509 "
+"private key and certificate."
+msgstr ""
+"Al hacer click en \"Descargar las credenciales EC2\" se descargará un "
+"fichero zip que incluye un fichero rc con sus claves de acceso, así como sus "
+"claves privadas x509 y certificado."
+
+#: dashboards/settings/project/forms.py:71
+#, python-format
+msgid "Error Downloading RC File: %s"
+msgstr "Error al descargar el fichero RC: %s"
+
+#: dashboards/settings/project/panel.py:25
+#: dashboards/settings/project/templates/project/_openrc.html:8
+#: dashboards/settings/project/templates/project/settings.html:3
+#: dashboards/settings/project/templates/project/settings.html:6
+msgid "OpenStack API"
+msgstr "OpenStack API"
+
+#: dashboards/settings/project/tables.py:27
+msgid "Service Name"
+msgstr "Nombre del Servicio"
+
+#: dashboards/settings/project/tables.py:29
+msgid "Service Endpoint"
+msgstr "Nodo del Servicio"
+
+#: dashboards/settings/project/tables.py:33
+msgid "API Endpoints"
+msgstr "Nodos API"
+
+#: dashboards/settings/project/templates/project/_openrc.html:15
+msgid "Download OpenStack RC File"
+msgstr "Descargar Fichero RC de OpenStack"
+
+#: dashboards/settings/project/templates/project/_openrc.html:25
+msgid ""
+"Download the RC file for the selected project, then type \"source openrc\" "
+"in the terminal to configure your environment to communicate with OpenStack."
+msgstr ""
+"Descargar el fichero RC para el proyecto seleccionado, para lo cual hay que "
+"escribir \"source openrc\" en la terminal para configurar el entorno para "
+"comunicarse con OpenStack."
+
+#: dashboards/settings/project/templates/project/_openrc.html:30
+msgid "Download RC File"
+msgstr "Descargar Fichero RC"
+
+#: dashboards/settings/user/forms.py:57
+msgid "Settings saved."
+msgstr "Ajustes guardados."
+
+#: dashboards/settings/user/panel.py:25
+#: dashboards/settings/user/templates/user/_settings.html:8
+#: dashboards/settings/user/templates/user/settings.html:3
+#: dashboards/settings/user/templates/user/settings.html:6
+msgid "User Settings"
+msgstr "Ajustes de Usuario"
+
+#: dashboards/settings/user/templates/user/_settings.html:18
+msgid "From here you can modify dashboard settings for your user."
+msgstr "Desde aquí puede modificar los ajustes del panel de su usuario."
+
#: templates/403.html:4 templates/403.html.py:9
msgid "Forbidden"
msgstr "Prohibido"
@@ -84,10 +3341,6 @@ msgstr "Prohibido"
msgid "Home"
msgstr "Página de inicio"
-#: templates/403.html:24 templates/404.html:23 templates/500.html:23
-msgid "Projects"
-msgstr "Proyectos"
-
#: templates/404.html:4
msgid "Page Not Found"
msgstr "Página no encontrada"
@@ -111,3 +3364,47 @@ msgid ""
msgstr ""
"Ha ocurrido un error inesperado mientras se procesaba la solicitud. Por "
"favor vuelva a intentarlo."
+
+#: templates/_header.html:3
+msgid "Logged in as"
+msgstr "Identificado como"
+
+#: templates/_header.html:6
+msgid "Help"
+msgstr "Ayuda"
+
+#: templates/_header.html:8
+msgid "Sign Out"
+msgstr "Salir"
+
+#: test/settings.py:50
+msgid "Password must be between 8 and 18 characters."
+msgstr "La contraseña debe tener entre 8 y 18 caracteres."
+
+#: usage/base.py:97
+msgid "Unable to retrieve usage information."
+msgstr "No ha sido posible obtener la información de utilización."
+
+#: usage/base.py:100
+msgid "You are viewing data for the future, which may or may not exist."
+msgstr "Está viendo datos del futuro, que pueden o no existir."
+
+#: usage/tables.py:11
+msgid "Download CSV Summary"
+msgstr "Descargar resumen en CSV"
+
+#: usage/tables.py:25
+msgid "VCPU Hours"
+msgstr "Horas VCPU"
+
+#: usage/tables.py:32
+msgid "Disk GB Hours"
+msgstr "Horas de disco GB"
+
+#: usage/tables.py:40 usage/tables.py:68
+msgid "Usage Summary"
+msgstr "Resumen de utilización"
+
+#: usage/tables.py:60
+msgid "Uptime"
+msgstr "Tiempo en funcionamiento"
diff --git a/openstack_dashboard/locale/fr/LC_MESSAGES/django.mo b/openstack_dashboard/locale/fr/LC_MESSAGES/django.mo
index 91dba7745..2d7241d11 100644
--- a/openstack_dashboard/locale/fr/LC_MESSAGES/django.mo
+++ b/openstack_dashboard/locale/fr/LC_MESSAGES/django.mo
Binary files differ
diff --git a/openstack_dashboard/locale/fr/LC_MESSAGES/django.po b/openstack_dashboard/locale/fr/LC_MESSAGES/django.po
index 2302b225a..5fddb2a74 100644
--- a/openstack_dashboard/locale/fr/LC_MESSAGES/django.po
+++ b/openstack_dashboard/locale/fr/LC_MESSAGES/django.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: openstack-dashboard\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-09-18 22:18+0000\n"
+"POT-Creation-Date: 2012-10-05 19:30+0000\n"
"PO-Revision-Date: 2012-05-08 00:20+0100\n"
"Last-Translator: Erwan Gallen <erwan@zinux.com>\n"
"Language-Team: French <fr@zinux.com>\n"
@@ -16,63 +16,3210 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
-#: settings.py:141
+#: settings.py:142
msgid "Bulgarian (Bulgaria)"
msgstr ""
-#: settings.py:142
+#: settings.py:143
msgid "Czech"
msgstr ""
-#: settings.py:143
+#: settings.py:144
msgid "English"
msgstr "Anglais"
-#: settings.py:144
+#: settings.py:145
msgid "Spanish"
msgstr "Espagnol"
-#: settings.py:145
+#: settings.py:146
msgid "French"
msgstr "Français"
-#: settings.py:146
+#: settings.py:147
msgid "Italiano"
msgstr "Italien"
-#: settings.py:147
+#: settings.py:148
msgid "Japanese"
msgstr "Japonais"
-#: settings.py:148
+#: settings.py:149
msgid "Korean (Korea)"
msgstr ""
-#: settings.py:149
+#: settings.py:150
msgid "Dutch (Netherlands)"
msgstr ""
-#: settings.py:150
+#: settings.py:151
msgid "Polish"
msgstr "Polonais"
-#: settings.py:151
+#: settings.py:152
msgid "Portuguese"
msgstr "Portugais"
-#: settings.py:152
+#: settings.py:153
#, fuzzy
msgid "Portuguese (Brazil)"
msgstr "Portugais"
-#: settings.py:153
+#: settings.py:154
msgid "Simplified Chinese"
msgstr "Chinois simplifié"
-#: settings.py:154
+#: settings.py:155
msgid "Traditional Chinese"
msgstr "Chinois traditionnel"
+#: api/keystone.py:56
+#, python-format
+msgid "%(type)s (%(backend)s backend)"
+msgstr ""
+
+#: api/nova.py:191
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(group)s"
+msgstr ""
+
+#: api/nova.py:196
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(cidr)s"
+msgstr ""
+
+#: api/nova.py:532
+msgid "Unknown instance"
+msgstr ""
+
+#: api/swift.py:217
+msgid "Unicode is not currently supported for object copy."
+msgstr ""
+
+#: dashboards/admin/dashboard.py:24
+msgid "System Panel"
+msgstr ""
+
+#: dashboards/admin/dashboard.py:30
+msgid "Admin"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:36 dashboards/admin/networks/forms.py:34
+#: dashboards/admin/networks/forms.py:69
+#: dashboards/admin/networks/ports/forms.py:40
+#: dashboards/admin/networks/ports/forms.py:72
+#: dashboards/admin/networks/ports/tables.py:73
+#: dashboards/admin/networks/subnets/tables.py:70
+#: dashboards/admin/projects/tables.py:87
+#: dashboards/admin/projects/workflows.py:71
+#: dashboards/admin/services/tables.py:38
+#: dashboards/admin/volumes/tables.py:10
+#: dashboards/project/access_and_security/security_groups/forms.py:36
+#: dashboards/project/access_and_security/security_groups/tables.py:58
+#: dashboards/project/images_and_snapshots/images/forms.py:40
+#: dashboards/project/images_and_snapshots/images/forms.py:115
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:9
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:10
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:77
+#: dashboards/project/instances/templates/instances/_detail_overview.html:9
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:9
+#: dashboards/project/networks/forms.py:37
+#: dashboards/project/networks/tables.py:94
+#: dashboards/project/networks/ports/tables.py:40
+#: dashboards/project/networks/subnets/forms.py:43
+#: dashboards/project/networks/subnets/forms.py:102
+#: dashboards/project/networks/subnets/tables.py:82
+#: dashboards/project/networks/templates/networks/_detail_overview.html:7
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:9
+#: dashboards/project/volumes/tables.py:144
+#: dashboards/project/volumes/tables.py:164
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:9
+msgid "Name"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:37 dashboards/admin/flavors/tables.py:41
+#: dashboards/admin/projects/workflows.py:39
+#: dashboards/project/instances/templates/instances/_detail_overview.html:26
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:10
+#: usage/tables.py:19
+msgid "VCPUs"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:38
+msgid "RAM MB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:39
+msgid "Root Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:40
+msgid "Ephemeral Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:50
+msgid "Unable to get unique ID for new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:67
+#, python-format
+msgid "Created flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:71
+msgid "Unable to create flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:92
+#, python-format
+msgid "Updated flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:96
+msgid "Unable to update flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/panel.py:29 dashboards/admin/flavors/tables.py:15
+#: dashboards/admin/flavors/tables.py:52
+#: dashboards/admin/flavors/templates/flavors/index.html:3
+#: dashboards/admin/flavors/templates/flavors/index.html:6
+msgid "Flavors"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:14
+#: dashboards/project/instances/workflows.py:177
+#: dashboards/project/instances/templates/instances/_detail_overview.html:22
+msgid "Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:23
+#: dashboards/admin/flavors/templates/flavors/_create.html:8
+#: dashboards/admin/flavors/templates/flavors/_create.html:23
+#: dashboards/admin/flavors/templates/flavors/create.html:3
+#: dashboards/admin/flavors/templates/flavors/create.html:6
+msgid "Create Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:30
+#: dashboards/admin/flavors/templates/flavors/_edit.html:8
+#: dashboards/admin/flavors/templates/flavors/edit.html:3
+#: dashboards/admin/flavors/templates/flavors/edit.html:6
+msgid "Edit Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:36
+#, python-format
+msgid "%sMB"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:40
+msgid "Flavor Name"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:43
+#: dashboards/project/instances/templates/instances/_detail_overview.html:24
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: usage/tables.py:22
+msgid "RAM"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:45
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+msgid "Root Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:47
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+msgid "Ephemeral Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:49
+msgid "Unable to retrieve flavor list."
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:76
+msgid "Unable to retrieve flavor data."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:17
+#: dashboards/admin/flavors/templates/flavors/_edit.html:17
+#: dashboards/admin/images/templates/images/_update.html:17
+#: dashboards/admin/networks/templates/networks/_create.html:17
+#: dashboards/admin/networks/templates/networks/ports/_create.html:17
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:17
+#: dashboards/admin/projects/tables.py:89
+#: dashboards/admin/projects/workflows.py:74
+#: dashboards/admin/projects/templates/projects/_add_user.html:17
+#: dashboards/admin/projects/templates/projects/_create.html:17
+#: dashboards/admin/projects/templates/projects/_create_user.html:17
+#: dashboards/admin/projects/templates/projects/_quotas.html:16
+#: dashboards/admin/projects/templates/projects/_update.html:17
+#: dashboards/admin/users/templates/users/_create.html:16
+#: dashboards/admin/users/templates/users/_update.html:16
+#: dashboards/project/access_and_security/security_groups/forms.py:38
+#: dashboards/project/access_and_security/security_groups/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:17
+#: dashboards/project/containers/templates/containers/_copy.html:16
+#: dashboards/project/containers/templates/containers/_create.html:16
+#: dashboards/project/containers/templates/containers/_upload.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/_create.html:16
+#: dashboards/project/networks/templates/networks/subnets/_create.html:17
+#: dashboards/project/volumes/forms.py:28
+#: dashboards/project/volumes/forms.py:195
+#: dashboards/project/volumes/tables.py:147
+#: dashboards/project/volumes/templates/volumes/_create.html:18
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:17
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:14
+msgid "Description"
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:18
+msgid "From here you can define the sizing of a new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:24
+#: dashboards/admin/flavors/templates/flavors/_edit.html:25
+#: dashboards/admin/images/templates/images/_update.html:24
+#: dashboards/admin/networks/templates/networks/_create.html:24
+#: dashboards/admin/networks/templates/networks/_update.html:23
+#: dashboards/admin/networks/templates/networks/ports/_create.html:24
+#: dashboards/admin/networks/templates/networks/ports/_update.html:28
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:24
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:32
+#: dashboards/admin/projects/templates/projects/_add_user.html:24
+#: dashboards/admin/projects/templates/projects/_create.html:24
+#: dashboards/admin/projects/templates/projects/_create_user.html:24
+#: dashboards/admin/projects/templates/projects/_quotas.html:23
+#: dashboards/admin/projects/templates/projects/_update.html:24
+#: dashboards/admin/users/templates/users/_create.html:23
+#: dashboards/admin/users/templates/users/_update.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:32
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:20
+#: dashboards/project/containers/templates/containers/_copy.html:23
+#: dashboards/project/containers/templates/containers/_create.html:23
+#: dashboards/project/containers/templates/containers/_upload.html:24
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:32
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:24
+#: dashboards/project/instances/templates/instances/_update.html:23
+#: dashboards/project/networks/templates/networks/_create.html:23
+#: dashboards/project/networks/templates/networks/_update.html:23
+#: dashboards/project/networks/templates/networks/subnets/_create.html:24
+#: dashboards/project/networks/templates/networks/subnets/_update.html:32
+#: dashboards/project/volumes/templates/volumes/_attach.html:24
+#: dashboards/project/volumes/templates/volumes/_create.html:56
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:24
+#: dashboards/settings/ec2/templates/ec2/download_form.html:24
+#: dashboards/settings/project/templates/project/_openrc.html:31
+#: dashboards/settings/user/templates/user/_settings.html:24
+msgid "Cancel"
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:18
+msgid "From here you can alter the sizing of the current flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:19
+msgid ""
+"Note: this will not affect the resources allocated to any existing instances "
+"using this flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:24
+#: dashboards/admin/projects/workflows.py:270
+#: dashboards/settings/user/templates/user/_settings.html:23
+msgid "Save"
+msgstr ""
+
+#: dashboards/admin/images/panel.py:29 dashboards/admin/images/tables.py:44
+#: dashboards/admin/images/templates/images/index.html:3
+#: dashboards/admin/images/templates/images/index.html:6
+#: dashboards/project/images_and_snapshots/images/tables.py:47
+#: dashboards/project/images_and_snapshots/images/tables.py:132
+msgid "Images"
+msgstr ""
+
+#: dashboards/admin/images/tables.py:40
+#: dashboards/project/images_and_snapshots/images/tables.py:113
+#: dashboards/project/instances/templates/instances/_detail_overview.html:74
+msgid "Image Name"
+msgstr ""
+
+#: dashboards/admin/images/views.py:55
+msgid "Unable to retrieve image list."
+msgstr ""
+
+#: dashboards/admin/images/templates/images/_update.html:8
+#: dashboards/admin/images/templates/images/_update.html:23
+#: dashboards/admin/images/templates/images/update.html:4
+#: dashboards/admin/images/templates/images/update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:22
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:6
+msgid "Update Image"
+msgstr ""
+
+#: dashboards/admin/images/templates/images/_update.html:18
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:17
+msgid "From here you can modify different properties of an image."
+msgstr ""
+
+#: dashboards/admin/instances/panel.py:29
+#: dashboards/admin/instances/tables.py:94
+#: dashboards/admin/instances/templates/instances/index.html:3
+#: dashboards/admin/projects/workflows.py:40
+#: dashboards/project/instances/panel.py:25
+#: dashboards/project/instances/tables.py:70
+#: dashboards/project/instances/tables.py:90
+#: dashboards/project/instances/tables.py:107
+#: dashboards/project/instances/tables.py:136
+#: dashboards/project/instances/tables.py:313
+#: dashboards/project/instances/templates/instances/index.html:3
+#: dashboards/project/instances/templates/instances/index.html:6
+msgid "Instances"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:60 usage/tables.py:30
+msgid "Project Name"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:67
+#: dashboards/admin/services/tables.py:40
+msgid "Host"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:71
+#: dashboards/project/instances/tables.py:290
+#: dashboards/project/instances/workflows.py:176 usage/tables.py:57
+msgid "Instance Name"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:72
+#: dashboards/project/access_and_security/floating_ips/tables.py:111
+#: dashboards/project/access_and_security/floating_ips/workflows.py:32
+#: dashboards/project/access_and_security/floating_ips/workflows.py:39
+#: dashboards/project/instances/tables.py:291
+msgid "IP Address"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:74
+#: dashboards/project/containers/tables.py:256
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:30
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:37
+#: dashboards/project/instances/tables.py:293
+#: dashboards/project/volumes/tables.py:150
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:26
+msgid "Size"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:79
+#: dashboards/admin/networks/tables.py:74
+#: dashboards/admin/networks/ports/tables.py:77
+#: dashboards/project/images_and_snapshots/images/tables.py:119
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:13
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:18
+#: dashboards/project/instances/tables.py:298
+#: dashboards/project/instances/templates/instances/_detail_overview.html:13
+#: dashboards/project/networks/tables.py:100
+#: dashboards/project/networks/ports/tables.py:44
+#: dashboards/project/networks/templates/networks/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:30
+#: dashboards/project/volumes/tables.py:154
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:17
+msgid "Status"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:83
+#: dashboards/project/instances/tables.py:302
+msgid "Task"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:90
+#: dashboards/project/instances/tables.py:309
+msgid "Power State"
+msgstr ""
+
+#: dashboards/admin/instances/views.py:49
+#: dashboards/project/access_and_security/views.py:76
+#: dashboards/project/access_and_security/floating_ips/workflows.py:65
+msgid "Unable to retrieve instance list."
+msgstr ""
+
+#: dashboards/admin/instances/views.py:63
+#: dashboards/admin/networks/views.py:48
+msgid "Unable to retrieve instance tenant information."
+msgstr ""
+
+#: dashboards/admin/instances/views.py:80
+#: dashboards/project/instances/views.py:82
+msgid "Unable to retrieve instance size information."
+msgstr ""
+
+#: dashboards/admin/instances/templates/instances/index.html:6
+msgid "All Instances"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:36
+#: dashboards/admin/networks/tables.py:67
+#: dashboards/admin/projects/tables.py:65 dashboards/project/dashboard.py:40
+#: dashboards/project/instances/workflows.py:38
+msgid "Project"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:37 dashboards/admin/networks/forms.py:74
+#: dashboards/admin/networks/tables.py:72
+#: dashboards/project/networks/tables.py:98
+#: dashboards/project/networks/templates/networks/_detail_overview.html:17
+msgid "Shared"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:46 dashboards/admin/users/forms.py:42
+msgid "Select a project"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:58
+#, python-format
+msgid "Network %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:64
+#, python-format
+msgid "Failed to create network %s"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:71
+#: dashboards/admin/networks/templates/networks/ports/_update.html:12
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:12
+#: dashboards/admin/users/forms.py:114
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:11
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:12
+#: dashboards/project/instances/templates/instances/_detail_overview.html:11
+#: dashboards/project/networks/forms.py:39
+#: dashboards/project/networks/templates/networks/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_update.html:12
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:11
+msgid "ID"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:82
+#: dashboards/project/networks/forms.py:48
+#, python-format
+msgid "Network %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:87
+#: dashboards/project/networks/forms.py:53
+#, python-format
+msgid "Failed to update network %s"
+msgstr ""
+
+#: dashboards/admin/networks/panel.py:25
+#: dashboards/admin/networks/tables.py:35
+#: dashboards/admin/networks/tables.py:80
+#: dashboards/admin/networks/templates/networks/index.html:3
+#: dashboards/admin/networks/templates/networks/index.html:6
+#: dashboards/project/instances/workflows.py:412
+#: dashboards/project/networks/panel.py:25
+#: dashboards/project/networks/tables.py:44
+#: dashboards/project/networks/tables.py:106
+#: dashboards/project/networks/templates/networks/index.html:3
+#: dashboards/project/networks/templates/networks/index.html:6
+msgid "Networks"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:34
+#: dashboards/project/networks/tables.py:43
+#: dashboards/project/networks/templates/networks/subnets/index.html:3
+#: dashboards/project/networks/templates/networks/subnets/index.html:6
+msgid "Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:41
+#: dashboards/project/networks/tables.py:59
+#, python-format
+msgid "Failed to delete network %s"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:49
+#: dashboards/admin/networks/templates/networks/_create.html:8
+#: dashboards/admin/networks/templates/networks/_create.html:23
+#: dashboards/admin/networks/templates/networks/create.html:3
+#: dashboards/admin/networks/templates/networks/create.html:6
+#: dashboards/project/networks/tables.py:67
+#: dashboards/project/networks/workflows.py:111
+#: dashboards/project/networks/templates/networks/_create.html:7
+#: dashboards/project/networks/templates/networks/_create.html:22
+#: dashboards/project/networks/templates/networks/create.html:3
+#: dashboards/project/networks/templates/networks/create.html:6
+msgid "Create Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:56
+#: dashboards/admin/networks/templates/networks/_update.html:7
+#: dashboards/project/networks/tables.py:74
+#: dashboards/project/networks/templates/networks/_update.html:7
+msgid "Edit Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:68
+#: dashboards/admin/networks/ports/forms.py:33
+#: dashboards/project/networks/subnets/forms.py:35
+msgid "Network Name"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:71
+#: dashboards/project/networks/tables.py:97
+msgid "Subnets Associated"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:76
+#: dashboards/admin/networks/ports/tables.py:79
+#: dashboards/project/networks/tables.py:102
+#: dashboards/project/networks/ports/tables.py:46
+#: dashboards/project/networks/templates/networks/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:32
+msgid "Admin State"
+msgstr ""
+
+#: dashboards/admin/networks/views.py:60
+#: dashboards/project/networks/views.py:52
+msgid "Network list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:91
+#: dashboards/project/networks/views.py:109
+msgid "Subnet list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:103
+#: dashboards/project/networks/views.py:121
+msgid "Port list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:118
+#: dashboards/project/networks/views.py:134
+#: dashboards/project/networks/subnets/tables.py:96
+#, python-format
+msgid "Unable to retrieve details for network \"%s\"."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:36
+#: dashboards/project/networks/subnets/forms.py:39
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:13
+msgid "Network ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:42
+#: dashboards/admin/networks/ports/forms.py:74
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:34
+msgid "Device ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:54
+#, python-format
+msgid "Port %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:59
+#, python-format
+msgid "Failed to create a port for network %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:84
+#, python-format
+msgid "Port %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:89
+#, python-format
+msgid "Failed to update port %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:34
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:6
+msgid "Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:35
+#: dashboards/admin/networks/ports/tables.py:83
+#: dashboards/project/networks/ports/tables.py:53
+msgid "Ports"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:41
+#: dashboards/admin/networks/subnets/tables.py:39
+#: dashboards/project/networks/subnets/tables.py:51
+#, python-format
+msgid "Failed to delete subnet %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:51
+#: dashboards/admin/networks/templates/networks/ports/_create.html:8
+#: dashboards/admin/networks/templates/networks/ports/_create.html:23
+#: dashboards/admin/networks/templates/networks/ports/create.html:3
+#: dashboards/admin/networks/templates/networks/ports/create.html:6
+msgid "Create Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:62
+#: dashboards/admin/networks/templates/networks/ports/_update.html:7
+msgid "Edit Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:75
+#: dashboards/project/networks/ports/tables.py:42
+msgid "Fixed IPs"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:76
+#: dashboards/project/networks/ports/tables.py:43
+msgid "Device Attached"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tabs.py:32
+#: dashboards/admin/overview/panel.py:29
+#: dashboards/admin/overview/templates/overview/usage.html:6
+#: dashboards/project/images_and_snapshots/images/tabs.py:27
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:27
+#: dashboards/project/instances/tabs.py:26
+#: dashboards/project/networks/ports/tabs.py:32
+#: dashboards/project/networks/subnets/tabs.py:32
+#: dashboards/project/overview/panel.py:29
+#: dashboards/project/overview/templates/overview/usage.html:6
+#: dashboards/project/volumes/tabs.py:27
+msgid "Overview"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tabs.py:42
+#: dashboards/project/networks/ports/tabs.py:42
+msgid "Unable to retrieve port details."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:49
+#: dashboards/admin/networks/subnets/views.py:49
+#: dashboards/project/networks/subnets/views.py:54
+msgid "Unable to retrieve network."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:82
+msgid "Unable to retrieve port details"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/forms.py:43
+#, python-format
+msgid "Failed to retrieve network %s for a subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:32
+#: dashboards/project/networks/subnets/tables.py:44
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:6
+msgid "Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:33
+#: dashboards/admin/networks/subnets/tables.py:81
+#: dashboards/project/networks/subnets/tables.py:45
+#: dashboards/project/networks/subnets/tables.py:104
+msgid "Subnets"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:49
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:8
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:23
+#: dashboards/admin/networks/templates/networks/subnets/create.html:3
+#: dashboards/admin/networks/templates/networks/subnets/create.html:6
+#: dashboards/project/networks/workflows.py:53
+#: dashboards/project/networks/subnets/tables.py:61
+#: dashboards/project/networks/templates/networks/subnets/_create.html:8
+#: dashboards/project/networks/templates/networks/subnets/_create.html:23
+#: dashboards/project/networks/templates/networks/subnets/create.html:3
+#: dashboards/project/networks/templates/networks/subnets/create.html:6
+msgid "Create Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:60
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:7
+#: dashboards/project/networks/subnets/tables.py:72
+#: dashboards/project/networks/templates/networks/subnets/_update.html:7
+msgid "Edit Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:72
+#: dashboards/project/access_and_security/security_groups/forms.py:91
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:15
+msgid "CIDR"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:73
+#: dashboards/project/networks/workflows.py:66
+#: dashboards/project/networks/subnets/forms.py:53
+#: dashboards/project/networks/subnets/tables.py:85
+msgid "IP Version"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:74
+#: dashboards/project/networks/subnets/forms.py:54
+#: dashboards/project/networks/subnets/forms.py:104
+#: dashboards/project/networks/subnets/tables.py:86
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:19
+msgid "Gateway IP"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/views.py:82
+#: dashboards/project/networks/subnets/views.py:86
+msgid "Unable to retrieve subnet details"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_create.html:18
+#: dashboards/project/networks/templates/networks/_create.html:17
+msgid "Select a name for your network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:16
+#: dashboards/admin/networks/templates/networks/ports/_update.html:21
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:25
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:17
+#: dashboards/project/instances/templates/instances/_update.html:16
+#: dashboards/project/networks/templates/networks/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_update.html:25
+#: dashboards/settings/ec2/templates/ec2/download_form.html:17
+#: dashboards/settings/project/templates/project/_openrc.html:24
+#: dashboards/settings/user/templates/user/_settings.html:17
+msgid "Description:"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:17
+#: dashboards/project/networks/templates/networks/_update.html:17
+msgid "You may update the editable properties of your network here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:22
+#: dashboards/admin/networks/templates/networks/ports/_update.html:27
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:31
+#: dashboards/project/instances/templates/instances/_update.html:22
+#: dashboards/project/networks/templates/networks/_update.html:22
+#: dashboards/project/networks/templates/networks/subnets/_update.html:31
+msgid "Save Changes"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/update.html:3
+#: dashboards/admin/networks/templates/networks/update.html:6
+#: dashboards/project/networks/templates/networks/update.html:3
+#: dashboards/project/networks/templates/networks/update.html:6
+msgid "Update Network"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_create.html:18
+msgid ""
+"You can create a port for the network. If you specify device ID to be "
+"attached, the device specified will be attached to the port created."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_update.html:22
+msgid "You may update the editable properties of your port here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/update.html:3
+#: dashboards/admin/networks/templates/networks/ports/update.html:6
+msgid "Update Port"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:18
+#: dashboards/project/networks/templates/networks/subnets/_create.html:18
+msgid ""
+"You can create a subnet for the network. Any network address can be "
+"specified unless the network address does not overlap other subnets in the "
+"network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:14
+#: dashboards/project/networks/workflows.py:58
+#: dashboards/project/networks/subnets/forms.py:45
+#: dashboards/project/networks/subnets/tables.py:84
+#: dashboards/project/networks/templates/networks/subnets/_update.html:14
+msgid "Network Address"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:17
+#: dashboards/project/networks/templates/networks/subnets/_update.html:16
+msgid "IP version"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:26
+#: dashboards/project/networks/templates/networks/subnets/_update.html:26
+msgid "You may update the editable properties of your subnet here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/index.html:3
+#: dashboards/admin/networks/templates/networks/subnets/index.html:6
+#: dashboards/project/networks/templates/networks/detail.html:3
+msgid "Network Detail"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/update.html:3
+#: dashboards/admin/networks/templates/networks/subnets/update.html:6
+#: dashboards/project/networks/templates/networks/subnets/update.html:3
+#: dashboards/project/networks/templates/networks/subnets/update.html:6
+msgid "Update Subnet"
+msgstr ""
+
+#: dashboards/admin/overview/templates/overview/usage.html:3
+msgid "Usage Overview"
+msgstr ""
+
+#: dashboards/admin/overview/templates/overview/usage.html:12
+msgid "Monitoring"
+msgstr ""
+
+#: dashboards/admin/projects/panel.py:29
+#: dashboards/admin/projects/tables.py:66
+#: dashboards/admin/projects/tables.py:95
+#: dashboards/admin/projects/templates/projects/index.html:8
+#: templates/403.html:24 templates/404.html:23 templates/500.html:23
+msgid "Projects"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:19
+msgid "Modify Users"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:32
+msgid "View Usage"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:39
+#: dashboards/admin/projects/templates/projects/_create.html:8
+#: dashboards/admin/projects/templates/projects/_create.html:23
+#: dashboards/admin/projects/templates/projects/create.html:6
+msgid "Create Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:46
+#: dashboards/admin/projects/workflows.py:269
+#: dashboards/admin/projects/templates/projects/update.html:3
+#: dashboards/admin/projects/templates/projects/update.html:6
+msgid "Edit Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:90
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:60
+#: dashboards/project/networks/templates/networks/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:15
+msgid "Project ID"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:91
+#: dashboards/admin/projects/workflows.py:76
+#: dashboards/admin/projects/workflows.py:251
+#: dashboards/admin/services/tables.py:42 dashboards/admin/users/tables.py:40
+#: dashboards/admin/users/tables.py:115
+msgid "Enabled"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:104
+msgid "Remove"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:105
+msgid "Removed"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:106 dashboards/admin/users/tables.py:41
+#: dashboards/admin/users/tables.py:75
+#: dashboards/project/instances/workflows.py:39
+msgid "User"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:107 dashboards/admin/users/panel.py:29
+#: dashboards/admin/users/tables.py:42 dashboards/admin/users/tables.py:76
+#: dashboards/admin/users/tables.py:122
+#: dashboards/admin/users/templates/users/index.html:8
+msgid "Users"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:125
+msgid "Unable to retrieve role information."
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:130
+msgid "Roles"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:134
+msgid "Users For Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:142
+msgid "Add To Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:154
+msgid "Add New Users"
+msgstr ""
+
+#: dashboards/admin/projects/views.py:67
+msgid "Unable to retrieve project information."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:87
+msgid "Unable to retrieve project list."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:110
+msgid "Unable to retrieve users."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:154
+msgid "Unable to retrieve default quota values."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:182
+msgid "Unable to retrieve project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:37
+msgid "Injected File Content Bytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:38
+msgid "Metadata Items"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:41
+msgid "Injected Files"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:44
+#: dashboards/admin/volumes/panel.py:9 dashboards/admin/volumes/tables.py:15
+#: dashboards/admin/volumes/templates/volumes/index.html:3
+#: dashboards/admin/volumes/templates/volumes/index.html:6
+#: dashboards/project/volumes/panel.py:25
+#: dashboards/project/volumes/tables.py:38
+#: dashboards/project/volumes/tables.py:171
+#: dashboards/project/volumes/tables.py:183
+#: dashboards/project/volumes/templates/volumes/index.html:3
+#: dashboards/project/volumes/templates/volumes/index.html:6
+msgid "Volumes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:45
+msgid "Gigabytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:46
+msgid "RAM (MB)"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:47
+#: dashboards/project/access_and_security/floating_ips/tables.py:50
+#: dashboards/project/access_and_security/floating_ips/tables.py:128
+msgid "Floating IPs"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:50
+msgid "Quota"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:52
+msgid "From here you can set quotas (max limits) for the project."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:81
+#: dashboards/admin/projects/workflows.py:254
+msgid "Project Info"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:82
+#: dashboards/admin/projects/templates/projects/_create.html:18
+msgid "From here you can create a new project to organize users."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:101
+msgid "Unable to retrieve user list. Please try again later."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:155
+#: dashboards/admin/projects/templates/projects/_update_members.html:16
+msgid "Project Members"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:169
+#: dashboards/admin/users/views.py:47
+msgid "Unable to retrieve user list."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:180
+msgid "Add Project"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:181
+msgid "Finish"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:182
+#, python-format
+msgid "Created new project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:183
+#, python-format
+msgid "Unable to create project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:227
+#, python-format
+msgid "Failed to add %s project members and set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:246
+msgid "Unable to set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:256
+msgid "From here you can edit the project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:271
+#, python-format
+msgid "Modified project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:272
+#, python-format
+msgid "Unable to modify project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:342
+#, python-format
+msgid "Failed to modify %s project members and update project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:363
+msgid ""
+"Modified project information and members, but unable to modify project "
+"quotas."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:8
+#: dashboards/admin/projects/templates/projects/add_user.html:3
+#: dashboards/admin/projects/templates/projects/add_user.html:6
+msgid "Add User To Project"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:18
+msgid "Select the user role for the project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:23
+msgid "Add"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:7
+#, python-format
+msgid "Create User for project '%(tenant_name)s'."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:18
+msgid "From here you can create a new user to add to this project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:23
+#: dashboards/admin/users/tables.py:20
+#: dashboards/admin/users/templates/users/_create.html:7
+#: dashboards/admin/users/templates/users/_create.html:22
+#: dashboards/admin/users/templates/users/create.html:7
+msgid "Create User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:7
+#: dashboards/admin/projects/templates/projects/_quotas.html:22
+msgid "Update Quota"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:17
+#, python-format
+msgid ""
+"From here you can edit quotas (max limits) for the project %(tenant.name)s."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update.html:8
+#: dashboards/admin/projects/templates/projects/_update.html:23
+#: dashboards/admin/projects/templates/projects/quotas.html:6
+msgid "Update Project"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update.html:18
+msgid "From here you can edit a project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:7
+msgid ""
+"From here you can add and remove members to this project from the list of "
+"all available users."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:10
+msgid "All Users"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:25
+#: dashboards/admin/projects/templates/projects/_update_members.html:32
+msgid "No users found."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/create_user.html:3
+#: dashboards/admin/projects/templates/projects/create_user.html:6
+msgid "Add New User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:3
+msgid "Project Usage Overview"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:7
+msgid "Project Usage"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/users.html:7
+msgid "Users for Project"
+msgstr ""
+
+#: dashboards/admin/quotas/panel.py:29 dashboards/admin/quotas/tables.py:36
+msgid "Quotas"
+msgstr ""
+
+#: dashboards/admin/quotas/tables.py:28
+msgid "Quota Name"
+msgstr ""
+
+#: dashboards/admin/quotas/tables.py:29
+msgid "Limit"
+msgstr ""
+
+#: dashboards/admin/quotas/views.py:46
+msgid "Unable to get quota info."
+msgstr ""
+
+#: dashboards/admin/quotas/templates/quotas/index.html:8
+msgid "Default Quotas"
+msgstr ""
+
+#: dashboards/admin/services/panel.py:29
+#: dashboards/admin/services/tables.py:47
+#: dashboards/admin/services/templates/services/index.html:8
+msgid "Services"
+msgstr ""
+
+#: dashboards/admin/services/tables.py:37
+msgid "Id"
+msgstr ""
+
+#: dashboards/admin/services/tables.py:39
+msgid "Service"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:54
+msgid "Passwords do not match."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:62 dashboards/admin/users/forms.py:115
+#: dashboards/admin/users/tables.py:108
+msgid "User Name"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:63 dashboards/admin/users/forms.py:116
+#: dashboards/admin/users/tables.py:109
+msgid "Email"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:65 dashboards/admin/users/forms.py:117
+msgid "Password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:70 dashboards/admin/users/forms.py:124
+msgid "Confirm Password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:73 dashboards/admin/users/forms.py:127
+msgid "Primary Project"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:75
+msgid "Role"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:96
+#, python-format
+msgid "User \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:106
+msgid "Unable to add userto primary project."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:110
+msgid "Unable to create user."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:151
+msgid "name"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:151
+msgid "email"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:160
+msgid "primary project"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:173
+#, python-format
+msgid "The user %s has no role defined for"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:181
+msgid "password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:190
+msgid "User has been updated successfully."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:194
+#, python-format
+msgid "Unable to update %(attributes)s for the user."
+msgstr ""
+
+#: dashboards/admin/users/tables.py:32
+#: dashboards/project/images_and_snapshots/images/tables.py:68
+msgid "Edit"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:39
+msgid "Enable"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:39
+msgid "Disable"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:40
+msgid "Disabled"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:63
+msgid "You cannot disable the user you are currently logged in as."
+msgstr ""
+
+#: dashboards/admin/users/tables.py:114
+msgid "User ID"
+msgstr ""
+
+#: dashboards/admin/users/views.py:70
+msgid "Unable to update user."
+msgstr ""
+
+#: dashboards/admin/users/views.py:104
+msgid "Unable to retrieve user roles."
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_create.html:17
+msgid "From here you can create a new user and assign them to a project."
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_update.html:7
+#: dashboards/admin/users/templates/users/_update.html:22
+#: dashboards/admin/users/templates/users/update.html:7
+msgid "Update User"
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_update.html:17
+msgid ""
+"From here you can edit the user's details, including their default project."
+msgstr ""
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:3
+#: dashboards/project/volumes/templates/volumes/detail.html:3
+msgid "Volume Details"
+msgstr ""
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:6
+#: dashboards/project/volumes/templates/volumes/detail.html:6
+msgid "Volume Detail"
+msgstr ""
+
+#: dashboards/project/dashboard.py:24
+msgid "Manage Compute"
+msgstr ""
+
+#: dashboards/project/dashboard.py:35
+msgid "Object Store"
+msgstr ""
+
+#: dashboards/project/access_and_security/panel.py:26
+#: dashboards/project/instances/workflows.py:348
+msgid "Access & Security"
+msgstr ""
+
+#: dashboards/project/access_and_security/views.py:51
+msgid "Unable to retrieve keypair list."
+msgstr ""
+
+#: dashboards/project/access_and_security/views.py:60
+#: dashboards/project/access_and_security/security_groups/views.py:74
+msgid "Unable to retrieve security groups."
+msgstr ""
+
+#: dashboards/project/access_and_security/views.py:69
+#: dashboards/project/access_and_security/floating_ips/workflows.py:49
+msgid "Unable to retrieve floating IP addresses."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:32
+msgid "Pool"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:43
+#, python-format
+msgid "Allocated Floating IP %(ip)s."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:47
+msgid "Unable to allocate Floating IP."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:37
+msgid "Allocate IP To Project"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:47
+msgid "Release"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:48
+msgid "Released"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:49
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:22
+msgid "Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:6
+#: dashboards/project/instances/tables.py:219
+msgid "Associate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:76
+msgid "Disassociate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:90
+#, python-format
+msgid "Successfully disassociated Floating IP: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:94
+msgid "Unable to disassociate floating IP."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:114
+#: dashboards/project/access_and_security/floating_ips/workflows.py:36
+#: dashboards/project/instances/tables.py:69
+#: dashboards/project/instances/tables.py:89
+#: dashboards/project/instances/tables.py:106
+#: dashboards/project/instances/tables.py:135
+#: dashboards/project/volumes/tables.py:206
+msgid "Instance"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:117
+msgid "Floating IP Pool"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:65
+msgid "Unable to retrieve floating IP pools."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:68
+msgid "No floating IP pools available."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:40
+msgid "Select the IP address you wish to associate with the selected instance."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:53
+msgid "Select an IP address"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:55
+msgid "No IP addresses available"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:76
+#: dashboards/project/volumes/forms.py:160
+msgid "Select an instance"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:78
+#: dashboards/project/volumes/forms.py:162
+msgid "No instances available"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:97
+msgid "Manage Floating IP Associations"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:98
+msgid "Associate"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:99
+#, python-format
+msgid "IP address %s associated."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:100
+#, python-format
+msgid "Unable to associate IP address %s."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:38
+#: dashboards/project/access_and_security/keypairs/forms.py:49
+#: dashboards/project/access_and_security/keypairs/tables.py:52
+msgid "Keypair Name"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:40
+msgid ""
+"Keypair names may only contain letters, numbers, underscores and hyphens."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:51
+msgid "Public Key"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:60
+#, python-format
+msgid "Successfully imported public key: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:65
+msgid "Unable to import keypair."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:30
+#: dashboards/project/instances/tables.py:295
+#: dashboards/project/instances/workflows.py:335
+msgid "Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:31
+#: dashboards/project/access_and_security/keypairs/tables.py:60
+msgid "Keypairs"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:39
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html:6
+msgid "Import Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:46
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html:6
+msgid "Create Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:53
+msgid "Fingerprint"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/views.py:74
+#, python-format
+msgid "Unable to create keypair: %(exc)s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:46
+#, python-format
+msgid "Successfully created security group: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:52
+msgid "Unable to create security group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:57
+#: dashboards/project/access_and_security/security_groups/tables.py:93
+msgid "IP Protocol"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:61
+msgid "The protocol which this rule should be applied to."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:65
+#: dashboards/project/access_and_security/security_groups/forms.py:71
+#: dashboards/project/access_and_security/security_groups/tables.py:95
+msgid "From Port"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:66
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP type in the range (-1: 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:72
+#: dashboards/project/images_and_snapshots/images/tables.py:115
+msgid "Type"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:74
+#: dashboards/project/access_and_security/security_groups/forms.py:80
+#: dashboards/project/access_and_security/security_groups/tables.py:96
+msgid "To Port"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:75
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP code in the range (-1: 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:81
+msgid "Code"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:84
+msgid "Source Group"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:86
+msgid ""
+"To specify an allowed IP range, select CIDR. To allow access from all "
+"members of another security group select Source Group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:94
+msgid "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:121
+msgid "The ICMP type is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:124
+msgid "The ICMP code is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:127
+msgid "The ICMP type not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:130
+msgid "The ICMP code not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:134
+msgid "The \"from\" port number is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:137
+msgid "The \"to\" port number is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:140
+msgid ""
+"The \"to\" port number must be greater than or equal to the \"from\" port "
+"number."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:146
+msgid "Either CIDR or Source Group may be specified, but not both."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:168
+#, python-format
+msgid "Successfully added rule: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:173
+msgid "Unable to add rule to security group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:31
+msgid "Security Group"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:32
+#: dashboards/project/access_and_security/security_groups/tables.py:66
+#: dashboards/project/instances/workflows.py:340
+#: dashboards/project/instances/templates/instances/_detail_overview.html:49
+msgid "Security Groups"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:45
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html:6
+msgid "Create Security Group"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:52
+msgid "Edit Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:72
+msgid "Rule"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:73
+msgid "Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:97
+msgid "Source"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:107
+msgid "Security Group Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/views.py:60
+msgid "Unable to retrieve security group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/views.py:80
+#, python-format
+msgid "%s (current)"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/index.html:6
+msgid "Access &amp; Security"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:8
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html:3
+msgid "Allocate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:18
+msgid "Allocate a floating IP from a given floating ip pool."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:20
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:19
+msgid "Project Quotas"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:31
+msgid "Allocate IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:17
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:17
+msgid ""
+"Keypairs are ssh credentials which are injected into images when they are "
+"launched. Creating a new key pair registers the public key and downloads the "
+"private key (a .pem file)."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:18
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:18
+msgid "Protect and use the key as you would any normal ssh private key."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:6
+msgid "Download Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:11
+#, python-format
+msgid ""
+"The keypair &quot;%(keypair_name)s&quot; should download automatically. If "
+"not use the link below."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:15
+#, python-format
+msgid "Download keypair &quot;%(keypair_name)s&quot;"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:18
+msgid "From here you can create a new security group"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:9
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html:6
+msgid "Edit Security Group Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:12
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:19
+msgid "Add Rule"
+msgstr ""
+
+#: dashboards/project/containers/browsers.py:26
+msgid "Swift"
+msgstr ""
+
+#: dashboards/project/containers/browsers.py:29
+#: dashboards/project/containers/tables.py:40
+msgid "Container"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:39
+msgid "Slash is not an allowed character."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:49
+#: dashboards/project/containers/tables.py:121
+msgid "Container Name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:57
+msgid "Container created successfully."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:68
+msgid "Folder created successfully."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:71
+msgid "Unable to create container."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:79
+#: dashboards/project/containers/tables.py:253
+msgid "Object Name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:81
+msgid "File"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:95
+msgid "Object was successfully uploaded."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:98
+msgid "Unable to upload object."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:102
+msgid "Destination container"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:106
+msgid "Destination object name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:137
+#: dashboards/project/containers/forms.py:163
+msgid "Unable to copy object."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:153
+#, python-format
+msgid "Copied \"%(orig)s\" to \"%(dest)s\" as \"%(new)s\"."
+msgstr ""
+
+#: dashboards/project/containers/panel.py:29
+#: dashboards/project/containers/tables.py:41
+#: dashboards/project/containers/tables.py:128
+#: dashboards/project/containers/templates/containers/index.html:7
+msgid "Containers"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:62
+#: dashboards/project/containers/templates/containers/_create.html:7
+#: dashboards/project/containers/templates/containers/_create.html:22
+#: dashboards/project/containers/templates/containers/create.html:6
+msgid "Create Container"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:69
+msgid "View Container"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:81
+#: dashboards/project/containers/templates/containers/_upload.html:23
+#: dashboards/project/containers/templates/containers/upload.html:3
+msgid "Upload Object"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:137
+#: dashboards/project/containers/tables.py:156
+msgid "Object"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:138
+#: dashboards/project/containers/tables.py:157
+#: dashboards/project/containers/tables.py:263
+msgid "Objects"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:149
+msgid "Folder"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:150
+msgid "Folders"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:163
+msgid "Copy"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:176
+msgid "Download"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:232
+msgid "Create Folder"
+msgstr ""
+
+#: dashboards/project/containers/views.py:53
+msgid "Unable to retrieve container list."
+msgstr ""
+
+#: dashboards/project/containers/views.py:82
+msgid "Unable to retrieve object list."
+msgstr ""
+
+#: dashboards/project/containers/views.py:166
+msgid "Unable to retrieve object."
+msgstr ""
+
+#: dashboards/project/containers/views.py:200
+msgid "Unable to list containers."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_copy.html:7
+#: dashboards/project/containers/templates/containers/_copy.html:22
+#: dashboards/project/containers/templates/containers/copy.html:3
+#: dashboards/project/containers/templates/containers/copy.html:6
+msgid "Copy Object"
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_copy.html:17
+msgid ""
+"Make a new copy of an existing object to store in this or another container. "
+"You may also specify a path at which the new copy should live inside of the "
+"selected container."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_create.html:17
+msgid ""
+"A container is a storage compartment for your data and provides a way for "
+"you to organize your data. You can think of a container as a folder in "
+"Windows &reg; or a directory in UNIX &reg;. The primary difference between a "
+"container and these other file system concepts is that containers cannot be "
+"nested. You can, however, create an unlimited number of containers within "
+"your account. Data must be stored in a container so you must have at least "
+"one container defined in your account prior to uploading data."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:8
+msgid "Upload Object To Container"
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:18
+msgid ""
+"An object is the basic storage entity and any optional metadata that "
+"represents the files you store in the OpenStack Object Storage system. When "
+"you upload data to OpenStack Object Storage, the data is stored as-is (no "
+"compression or encryption) and consists of a location (container), the "
+"object's name, and any metadata consisting of key/value pairs."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/upload.html:6
+msgid "Upload Objects"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/panel.py:26
+msgid "Images & Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:63
+msgid "Unable to retrieve images."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:74
+msgid "Unable to retrieve snapshots."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:82
+#: dashboards/project/volumes/forms.py:65
+msgid "Unable to retrieve volume snapshots."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:42
+msgid "Image Location"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:43
+msgid "An external (HTTP) URL to load the image from."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:46
+#: dashboards/project/images_and_snapshots/images/forms.py:130
+#: dashboards/project/images_and_snapshots/images/tables.py:126
+msgid "Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:50
+msgid "AKI - Amazon Kernel Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:53
+msgid "AMI - Amazon Machine Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:56
+msgid "ARI - Amazon Ramdisk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:59
+msgid "ISO - Optical Disk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:61
+msgid "QCOW2 - QEMU Emulator"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:68
+msgid "Minimum Disk (GB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:69
+#: dashboards/project/images_and_snapshots/images/forms.py:76
+msgid ""
+"The minimum disk size required to boot the image. If unspecified, this value "
+"defaults to 0 (no minimum)."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:75
+msgid "Minimum Ram (MB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:82
+#: dashboards/project/images_and_snapshots/images/forms.py:134
+#: dashboards/project/images_and_snapshots/images/tables.py:123
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:15
+msgid "Public"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:106
+#, python-format
+msgid "Your image %s has been queued for creation."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:110
+msgid "Unable to create new image."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:116
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:48
+msgid "Kernel ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:121
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:52
+msgid "Ramdisk ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:126
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:44
+msgid "Architecture"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:138
+#, python-format
+msgid "Unable to update image \"%s\"."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:162
+msgid "Image was successfully updated."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tables.py:34
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:33
+#: dashboards/project/instances/workflows.py:455
+msgid "Launch"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tables.py:46
+#: dashboards/project/images_and_snapshots/images/tables.py:82
+#: dashboards/project/instances/workflows.py:168
+#: dashboards/project/instances/workflows.py:173
+msgid "Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tables.py:61
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:31
+msgid "Create Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tabs.py:38
+msgid "Unable to retrieve image details."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/views.py:61
+msgid "Unable to retrieve image."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:37
+msgid "Instance ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:40
+#: dashboards/project/volumes/forms.py:193
+msgid "Snapshot Name"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:50
+#, python-format
+msgid "Snapshot \"%(name)s\" created for instance \"%(inst)s\""
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:56
+msgid "Unable to create snapshot."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:48
+#: dashboards/project/instances/workflows.py:107
+#: dashboards/project/instances/workflows.py:169
+msgid "Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:49
+msgid "Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:55
+msgid "Instance Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/views.py:53
+msgid "Unable to retrieve instance."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:6
+msgid "Images &amp; Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:6
+msgid "Create An Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:18
+msgid "Specify an image to upload to the Image Service."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:21
+msgid ""
+"Currently only images available via an HTTP URL are supported. The image "
+"location must be accessible to the Image Service. Compressed image binaries "
+"are supported (.zip and .tar.gz.)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:24
+msgid "Please note: "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:25
+msgid ""
+"The Image Location field MUST be a valid and direct URL to the image binary. "
+"URLs that redirect or serve error pages will result in unusable images."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:3
+msgid "Image Overview"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:6
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:7
+#: dashboards/project/instances/templates/instances/_detail_overview.html:6
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:6
+msgid "Info"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:17
+msgid "Checksum"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:19
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:39
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:28
+msgid "Created"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:21
+msgid "Updated"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:27
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:34
+#: dashboards/project/instances/templates/instances/_detail_overview.html:19
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:23
+msgid "Specs"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:32
+msgid "Container Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:34
+msgid "Disk Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:40
+msgid "Custom Properties"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:56
+msgid "Euca2ools state"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:64
+msgid "Image Type"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html:4
+msgid "Image Detail "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:8
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:3
+#: dashboards/project/instances/tables.py:179
+#: dashboards/project/volumes/tables.py:76
+msgid "Create Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:18
+msgid "Snapshots preserve the disk state of a running instance."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:20
+#: dashboards/project/instances/workflows.py:75
+#: dashboards/project/instances/workflows.py:110
+#: dashboards/project/instances/templates/instances/_detail_overview.html:93
+#: dashboards/project/volumes/tables.py:37
+#: dashboards/project/volumes/tables.py:182
+msgid "Volume"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:38
+#: dashboards/project/instances/templates/instances/_detail_overview.html:29
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:27
+msgid "GB"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:6
+msgid "Create a Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:3
+msgid "Volume Snapshot Details"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:6
+msgid "Volume Snapshot Detail"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:34
+#: dashboards/project/instances/workflows.py:76
+msgid "Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:35
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:85
+msgid "Volume Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:43
+#: dashboards/project/volumes/tables.py:59
+#: dashboards/project/volumes/templates/volumes/_create.html:8
+#: dashboards/project/volumes/templates/volumes/_create.html:55
+msgid "Create Volume"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:80
+#: dashboards/project/volumes/forms.py:26
+msgid "Volume Name"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:41
+msgid "Unable to retrieve snapshot details."
+msgstr ""
+
+#: dashboards/project/instances/forms.py:45
+#, python-format
+msgid "Instance \"%s\" updated."
+msgstr ""
+
+#: dashboards/project/instances/forms.py:50
+msgid "Unable to update instance."
+msgstr ""
+
+#: dashboards/project/instances/tables.py:67
+msgid "Terminate"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:68
+msgid "Scheduled termination of"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:87
+msgid "Reboot"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:88
+msgid "Rebooted"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:104
+msgid "Pause"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:104
+msgid "Unpause"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:105
+msgid "Paused"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:105
+msgid "Unpaused"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:133
+msgid "Suspend"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:133
+msgid "Resume"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:134
+msgid "Suspended"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:134
+msgid "Resumed"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:162
+#: dashboards/project/instances/workflows.py:454
+#: dashboards/project/instances/templates/instances/launch.html:3
+#: dashboards/project/instances/templates/instances/launch.html:6
+msgid "Launch Instance"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:169
+#: dashboards/project/instances/templates/instances/_update.html:7
+msgid "Edit Instance"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:189
+msgid "VNC Console"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:204
+msgid "View Log"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:252
+#, python-format
+msgid "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disk"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:259
+#: dashboards/project/instances/tables.py:266
+msgid "Not available"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:36
+msgid "Log"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:48
+#: dashboards/project/instances/views.py:106
+#, python-format
+msgid "Unable to get log for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:55
+msgid "VNC"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:70
+#: dashboards/project/instances/views.py:122
+#, python-format
+msgid "Unable to get VNC console for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/views.py:59
+msgid "Unable to retrieve instances."
+msgstr ""
+
+#: dashboards/project/instances/views.py:144
+msgid "Unable to retrieve instance details."
+msgstr ""
+
+#: dashboards/project/instances/views.py:179
+#, python-format
+msgid "Unable to retrieve details for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:53
+msgid "Project & User"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:66
+msgid "Don't boot from a volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:67
+msgid "Boot from volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:68
+msgid "Boot from volume snapshot (creates a new volume)."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:72
+#: dashboards/project/instances/workflows.py:90
+msgid "Volume Options"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:78
+#: dashboards/project/volumes/forms.py:126
+msgid "Device Name"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:81
+msgid "Volume mount point (e.g. 'vda' mounts at '/dev/vda')."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:83
+msgid "Delete on Terminate"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:86
+msgid "Delete volume on instance terminate"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:100
+#, python-format
+msgid "Please choose a volume, or select %s."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:117
+msgid "Select Volume"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:125
+msgid "Unable to retrieve list of volumes."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:129
+msgid "Select Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:138
+msgid "Unable to retrieve list of volume snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:171
+msgid "Instance Source"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:174
+msgid "Instance Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:178
+msgid "Size of image to launch."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:179
+msgid "Instance Count"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:182
+msgid "Number of instances to launch."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:185
+msgid "Details"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:198
+msgid ""
+"There are no image sources available; you must first create an image before "
+"attempting to launch an instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:203
+msgid "Please select an option for the instance source."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:212
+msgid ""
+"Launching multiple instances is only supported for images and instance "
+"snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:229
+msgid "Unable to retrieve public images."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:244
+msgid "Unable to retrieve images for the current project."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:267
+msgid "Select Image"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:269
+msgid "No images available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:278
+msgid "Select Instance Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:280
+msgid "No snapshots available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:291
+msgid "Unable to retrieve instance flavors."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:304 usage/base.py:114
+msgid "Unable to retrieve quota information."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:337
+msgid "Which keypair to use for authentication."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:344
+msgid "Launch instance in these security groups."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:349
+msgid ""
+"Control access to your instance via keypairs, security groups, and other "
+"mechanisms."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:359
+msgid "Unable to retrieve keypairs."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:361
+msgid "Select a keypair"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:363
+msgid "No keypairs available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:372
+msgid "Unable to retrieve list of security groups"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:392
+msgid "Customization Script"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:394
+msgid ""
+"A script or set of commands to be executed after the instance has been built "
+"(max 16kb)."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:401
+msgid "Post-Creation"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:415
+msgid "Launch instance withthese networks"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:419
+msgid "Networking"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:421
+msgid "Select networks for your instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:433
+msgid "Unable to retrieve networks."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:456
+#, python-format
+msgid "Launched %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:457
+#, python-format
+msgid "Unable to launch %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:470
+#, python-format
+msgid "%s instances"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:473
+msgid "instance"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:4
+msgid "Instance Console Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:7
+msgid "Log Length"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:9
+msgid "Go"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:11
+msgid "View Full Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:3
+msgid "Instance Overview"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:27
+msgid "VCPU"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:28
+#: usage/tables.py:20
+msgid "Disk"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:34
+msgid "IP Addresses"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:59
+msgid "No rules defined."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:68
+msgid "Meta"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:71
+msgid "Key Name"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:84
+msgid "Volumes Attached"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:88
+#: dashboards/project/volumes/tables.py:167
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:38
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:45
+msgid "Attached To"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:90
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:42
+msgid "on"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:94
+msgid "No volumes attached."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:3
+msgid "Instance VNC Console"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid ""
+"If VNC console is not responding to keyboard input: click the grey status "
+"bar below."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid "Click here to show only VNC"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:8
+msgid "VNC console is currently unavailabe. Please try again later."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:9
+msgid "Reload"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:2
+msgid ""
+"You can customize your instance after it's launched using the options "
+"available here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:3
+msgid ""
+"The \"Customization Script\" field is analogous to \"User Data\" in other "
+"systems."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:3
+msgid "Specify the details for launching an instance."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:4
+msgid ""
+"The chart below shows the resources used by this project in relation to the "
+"project's quotas."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:6
+msgid "Flavor Details"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+msgid "Total Disk"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "MB"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:21
+msgid "Number of Instances"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:29
+msgid "Number of VCPUs"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "Total RAM"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_volumes_help.html:3
+msgid ""
+"An instance can be launched with varying types of attached storage. You may "
+"select from those options here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_update.html:17
+msgid "You may update the editable properties of your instance here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/detail.html:3
+msgid "Instance Detail"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/update.html:3
+#: dashboards/project/instances/templates/instances/update.html:6
+msgid "Update Instance"
+msgstr ""
+
+#: dashboards/project/networks/tables.py:81
+msgid "Add Subnet"
+msgstr ""
+
+#: dashboards/project/networks/views.py:86
+msgid "Unable to retrieve network details."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:37
+msgid "Network Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:42
+msgid ""
+"From here you can create a new network.\n"
+"In addition a subnet associated with the network can be created in the next "
+"panel."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:56
+msgid "Subnet Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:61
+#: dashboards/project/networks/subnets/forms.py:48
+msgid "Network address in CIDR format (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:67
+msgid "Gateway IP (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:70
+#: dashboards/project/networks/subnets/forms.py:57
+#: dashboards/project/networks/subnets/forms.py:107
+msgid "IP address of Gateway (e.g. 192.168.0.1)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:77
+msgid ""
+"You can create a subnet associated with the new network, in which case "
+"\"Network Address\" must be specified. If you wish to create a network "
+"WITHOUT a subnet, uncheck the \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:89
+msgid "Specify \"Network Address\" or clear \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:94
+#: dashboards/project/networks/subnets/forms.py:70
+msgid "Network Address and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:98
+#: dashboards/project/networks/subnets/forms.py:74
+#: dashboards/project/networks/subnets/forms.py:119
+msgid "Gateway IP and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:112
+msgid "Create"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:113
+#, python-format
+msgid "Created network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:114
+#, python-format
+msgid "Unable to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:130
+#, python-format
+msgid "Network \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:133
+#, python-format
+msgid "Failed to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:152
+#, python-format
+msgid "Subnet \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:155
+#, python-format
+msgid "Failed to create subnet \"%(sub)s\" for network \"%(net)s\"."
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Attached"
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Detached"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:85
+#, python-format
+msgid "Subnet %s was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:90
+#, python-format
+msgid "Failed to create subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:131
+#, python-format
+msgid "Subnet %s was successfully updated."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:136
+#, python-format
+msgid "Failed to update subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/tabs.py:42
+msgid "Unable to retrieve subnet details."
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/_detail_overview.html:3
+msgid "Network Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/detail.html:6
+msgid "Network Detail: "
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:3
+msgid "Port Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:17
+msgid "Fixed IP"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:21
+msgid "IP address:"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:22
+msgid "Subnet ID"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:28
+msgid "Mac Address"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/detail.html:3
+#: dashboards/project/networks/templates/networks/ports/detail.html:6
+msgid "Port Detail"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:3
+msgid "Subnet Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:21
+msgid "IP allocation pool"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:24
+msgid "Start"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:25
+msgid " - End"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/detail.html:3
+#: dashboards/project/networks/templates/networks/subnets/detail.html:6
+msgid "Subnet Detail"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:29
+msgid "Size (GB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:30
+msgid "Use snapshot as a source"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:49
+#, python-format
+msgid "Volume size must be equal to or greater than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:54
+msgid "Unable to load the specified snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:59
+msgid "Choose a snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:83
+#, python-format
+msgid "The volume size cannot be less than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:92
+#, python-format
+msgid ""
+"A volume of %(req)iGB cannot be created as you only have %(avail)iGB of your "
+"quota available."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:99
+msgid "You are already using all of your available volumes."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:115
+msgid "Unable to create volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:123
+msgid "Attach to Instance"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:124
+msgid "Select an instance to attach to."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:168
+msgid "Unknown instance (None)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:179
+#, python-format
+msgid "Attaching volume %(vol)s to instance %(inst)s on %(dev)s."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:188
+msgid "Unable to attach volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:212
+#, python-format
+msgid "Creating volume snapshot \"%s\""
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:218
+msgid "Unable to create volume snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:46
+#, python-format
+msgid "Unable to delete volume \"%s\". One or more snapshots depend on it."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:66
+msgid "Edit Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:93
+#, python-format
+msgid "%sGB"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:106
+#: dashboards/project/volumes/views.py:149
+msgid "Unable to retrieve attachment information."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:123
+#, python-format
+msgid "Attached to %(instance)s on %(dev)s"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:180
+msgid "Detach"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:181
+msgid "Detaching"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:216
+#, python-format
+msgid "%(dev)s on instance %(instance_name)s"
+msgstr ""
+
+#: dashboards/project/volumes/tabs.py:42
+msgid "Unable to retrieve volume details."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:50
+msgid "Unable to retrieve volume list."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:58
+msgid "Unable to retrieve volume/instance attachment information"
+msgstr ""
+
+#: dashboards/project/volumes/views.py:130
+#: dashboards/project/volumes/views.py:140
+msgid "Unable to retrieve volume information."
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:9
+#: dashboards/project/volumes/templates/volumes/attach.html:6
+msgid "Manage Volume Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:13
+msgid "Attach To Instance"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:22
+msgid "Attach Volume"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:20
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:18
+msgid "Volumes are block devices that can be attached to instances."
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:22
+msgid "Volume Quotas"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:25
+msgid "Total Gigabytes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:34
+msgid "Number of Volumes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:8
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:23
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:3
+msgid "Create Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:3
+msgid "Volume Overview"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:34
+msgid "Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:46
+msgid "Not attached"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/create.html:6
+msgid "Create a Volume"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:6
+msgid "Create a Volume Snapshot"
+msgstr ""
+
+#: dashboards/settings/dashboard.py:24 templates/_header.html:4
+msgid "Settings"
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:36 dashboards/settings/project/forms.py:36
+msgid "Select a Project"
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:46
+msgid "Unable to retrieve tenant list."
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:88
+msgid "Unable to fetch EC2 credentials."
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:101
+#, python-format
+msgid "Error writing zipfile: %(exc)s"
+msgstr ""
+
+#: dashboards/settings/ec2/panel.py:25
+msgid "EC2 Credentials"
+msgstr ""
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:8
+#: dashboards/settings/ec2/templates/ec2/download_form.html:23
+#: dashboards/settings/ec2/templates/ec2/index.html:3
+#: dashboards/settings/ec2/templates/ec2/index.html:6
+msgid "Download EC2 Credentials"
+msgstr ""
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:18
+msgid ""
+"Clicking \"Download EC2 Credentials\" will download a zip file which "
+"includes an rc file with your access/secret keys, as well as your x509 "
+"private key and certificate."
+msgstr ""
+
+#: dashboards/settings/project/forms.py:71
+#, python-format
+msgid "Error Downloading RC File: %s"
+msgstr ""
+
+#: dashboards/settings/project/panel.py:25
+#: dashboards/settings/project/templates/project/_openrc.html:8
+#: dashboards/settings/project/templates/project/settings.html:3
+#: dashboards/settings/project/templates/project/settings.html:6
+msgid "OpenStack API"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:27
+msgid "Service Name"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:29
+msgid "Service Endpoint"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:33
+msgid "API Endpoints"
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:15
+msgid "Download OpenStack RC File"
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:25
+msgid ""
+"Download the RC file for the selected project, then type \"source openrc\" "
+"in the terminal to configure your environment to communicate with OpenStack."
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:30
+msgid "Download RC File"
+msgstr ""
+
+#: dashboards/settings/user/forms.py:57
+msgid "Settings saved."
+msgstr ""
+
+#: dashboards/settings/user/panel.py:25
+#: dashboards/settings/user/templates/user/_settings.html:8
+#: dashboards/settings/user/templates/user/settings.html:3
+#: dashboards/settings/user/templates/user/settings.html:6
+msgid "User Settings"
+msgstr ""
+
+#: dashboards/settings/user/templates/user/_settings.html:18
+msgid "From here you can modify dashboard settings for your user."
+msgstr ""
+
#: templates/403.html:4 templates/403.html.py:9
msgid "Forbidden"
msgstr "Interdit"
@@ -81,10 +3228,6 @@ msgstr "Interdit"
msgid "Home"
msgstr "Accueil"
-#: templates/403.html:24 templates/404.html:23 templates/500.html:23
-msgid "Projects"
-msgstr "Projets"
-
#: templates/404.html:4
msgid "Page Not Found"
msgstr "Page non trouvée"
@@ -109,3 +3252,47 @@ msgid ""
msgstr ""
"Une erreur inattendue s'est produite lors du traitement de votre demande. "
"Veuillez essayer à nouveau votre demande."
+
+#: templates/_header.html:3
+msgid "Logged in as"
+msgstr ""
+
+#: templates/_header.html:6
+msgid "Help"
+msgstr ""
+
+#: templates/_header.html:8
+msgid "Sign Out"
+msgstr ""
+
+#: test/settings.py:50
+msgid "Password must be between 8 and 18 characters."
+msgstr ""
+
+#: usage/base.py:97
+msgid "Unable to retrieve usage information."
+msgstr ""
+
+#: usage/base.py:100
+msgid "You are viewing data for the future, which may or may not exist."
+msgstr ""
+
+#: usage/tables.py:11
+msgid "Download CSV Summary"
+msgstr ""
+
+#: usage/tables.py:25
+msgid "VCPU Hours"
+msgstr ""
+
+#: usage/tables.py:32
+msgid "Disk GB Hours"
+msgstr ""
+
+#: usage/tables.py:40 usage/tables.py:68
+msgid "Usage Summary"
+msgstr ""
+
+#: usage/tables.py:60
+msgid "Uptime"
+msgstr ""
diff --git a/openstack_dashboard/locale/it/LC_MESSAGES/django.mo b/openstack_dashboard/locale/it/LC_MESSAGES/django.mo
new file mode 100644
index 000000000..7fe047a7d
--- /dev/null
+++ b/openstack_dashboard/locale/it/LC_MESSAGES/django.mo
Binary files differ
diff --git a/openstack_dashboard/locale/it/LC_MESSAGES/django.po b/openstack_dashboard/locale/it/LC_MESSAGES/django.po
new file mode 100644
index 000000000..d1a9e4172
--- /dev/null
+++ b/openstack_dashboard/locale/it/LC_MESSAGES/django.po
@@ -0,0 +1,3347 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-10-05 19:30+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+#: settings.py:142
+msgid "Bulgarian (Bulgaria)"
+msgstr ""
+
+#: settings.py:143
+msgid "Czech"
+msgstr ""
+
+#: settings.py:144
+msgid "English"
+msgstr ""
+
+#: settings.py:145
+msgid "Spanish"
+msgstr ""
+
+#: settings.py:146
+msgid "French"
+msgstr ""
+
+#: settings.py:147
+msgid "Italiano"
+msgstr ""
+
+#: settings.py:148
+msgid "Japanese"
+msgstr ""
+
+#: settings.py:149
+msgid "Korean (Korea)"
+msgstr ""
+
+#: settings.py:150
+msgid "Dutch (Netherlands)"
+msgstr ""
+
+#: settings.py:151
+msgid "Polish"
+msgstr ""
+
+#: settings.py:152
+#, fuzzy
+msgid "Portuguese"
+msgstr "Porte"
+
+#: settings.py:153
+msgid "Portuguese (Brazil)"
+msgstr ""
+
+#: settings.py:154
+msgid "Simplified Chinese"
+msgstr ""
+
+#: settings.py:155
+msgid "Traditional Chinese"
+msgstr ""
+
+#: api/keystone.py:56
+#, python-format
+msgid "%(type)s (%(backend)s backend)"
+msgstr ""
+
+#: api/nova.py:191
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(group)s"
+msgstr ""
+
+#: api/nova.py:196
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(cidr)s"
+msgstr ""
+
+#: api/nova.py:532
+msgid "Unknown instance"
+msgstr "Istanza sconosciuta"
+
+#: api/swift.py:217
+msgid "Unicode is not currently supported for object copy."
+msgstr "Unicode non è attualmente supportato per la copia di oggetti"
+
+#: dashboards/admin/dashboard.py:24
+msgid "System Panel"
+msgstr "Panello di sistema"
+
+#: dashboards/admin/dashboard.py:30
+msgid "Admin"
+msgstr "Amministratore"
+
+#: dashboards/admin/flavors/forms.py:36 dashboards/admin/networks/forms.py:34
+#: dashboards/admin/networks/forms.py:69
+#: dashboards/admin/networks/ports/forms.py:40
+#: dashboards/admin/networks/ports/forms.py:72
+#: dashboards/admin/networks/ports/tables.py:73
+#: dashboards/admin/networks/subnets/tables.py:70
+#: dashboards/admin/projects/tables.py:87
+#: dashboards/admin/projects/workflows.py:71
+#: dashboards/admin/services/tables.py:38
+#: dashboards/admin/volumes/tables.py:10
+#: dashboards/project/access_and_security/security_groups/forms.py:36
+#: dashboards/project/access_and_security/security_groups/tables.py:58
+#: dashboards/project/images_and_snapshots/images/forms.py:40
+#: dashboards/project/images_and_snapshots/images/forms.py:115
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:9
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:10
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:77
+#: dashboards/project/instances/templates/instances/_detail_overview.html:9
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:9
+#: dashboards/project/networks/forms.py:37
+#: dashboards/project/networks/tables.py:94
+#: dashboards/project/networks/ports/tables.py:40
+#: dashboards/project/networks/subnets/forms.py:43
+#: dashboards/project/networks/subnets/forms.py:102
+#: dashboards/project/networks/subnets/tables.py:82
+#: dashboards/project/networks/templates/networks/_detail_overview.html:7
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:9
+#: dashboards/project/volumes/tables.py:144
+#: dashboards/project/volumes/tables.py:164
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:9
+msgid "Name"
+msgstr "Nome"
+
+#: dashboards/admin/flavors/forms.py:37 dashboards/admin/flavors/tables.py:41
+#: dashboards/admin/projects/workflows.py:39
+#: dashboards/project/instances/templates/instances/_detail_overview.html:26
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:10
+#: usage/tables.py:19
+msgid "VCPUs"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:38
+msgid "RAM MB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:39
+msgid "Root Disk GB"
+msgstr "Disco principale in GB"
+
+#: dashboards/admin/flavors/forms.py:40
+msgid "Ephemeral Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:50
+msgid "Unable to get unique ID for new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:67
+#, python-format
+msgid "Created flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:71
+msgid "Unable to create flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:92
+#, python-format
+msgid "Updated flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:96
+msgid "Unable to update flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/panel.py:29 dashboards/admin/flavors/tables.py:15
+#: dashboards/admin/flavors/tables.py:52
+#: dashboards/admin/flavors/templates/flavors/index.html:3
+#: dashboards/admin/flavors/templates/flavors/index.html:6
+msgid "Flavors"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:14
+#: dashboards/project/instances/workflows.py:177
+#: dashboards/project/instances/templates/instances/_detail_overview.html:22
+msgid "Flavor"
+msgstr "Flavor"
+
+#: dashboards/admin/flavors/tables.py:23
+#: dashboards/admin/flavors/templates/flavors/_create.html:8
+#: dashboards/admin/flavors/templates/flavors/_create.html:23
+#: dashboards/admin/flavors/templates/flavors/create.html:3
+#: dashboards/admin/flavors/templates/flavors/create.html:6
+msgid "Create Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:30
+#: dashboards/admin/flavors/templates/flavors/_edit.html:8
+#: dashboards/admin/flavors/templates/flavors/edit.html:3
+#: dashboards/admin/flavors/templates/flavors/edit.html:6
+msgid "Edit Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:36
+#, python-format
+msgid "%sMB"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:40
+msgid "Flavor Name"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:43
+#: dashboards/project/instances/templates/instances/_detail_overview.html:24
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: usage/tables.py:22
+msgid "RAM"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:45
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+msgid "Root Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:47
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+msgid "Ephemeral Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:49
+msgid "Unable to retrieve flavor list."
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:76
+msgid "Unable to retrieve flavor data."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:17
+#: dashboards/admin/flavors/templates/flavors/_edit.html:17
+#: dashboards/admin/images/templates/images/_update.html:17
+#: dashboards/admin/networks/templates/networks/_create.html:17
+#: dashboards/admin/networks/templates/networks/ports/_create.html:17
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:17
+#: dashboards/admin/projects/tables.py:89
+#: dashboards/admin/projects/workflows.py:74
+#: dashboards/admin/projects/templates/projects/_add_user.html:17
+#: dashboards/admin/projects/templates/projects/_create.html:17
+#: dashboards/admin/projects/templates/projects/_create_user.html:17
+#: dashboards/admin/projects/templates/projects/_quotas.html:16
+#: dashboards/admin/projects/templates/projects/_update.html:17
+#: dashboards/admin/users/templates/users/_create.html:16
+#: dashboards/admin/users/templates/users/_update.html:16
+#: dashboards/project/access_and_security/security_groups/forms.py:38
+#: dashboards/project/access_and_security/security_groups/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:17
+#: dashboards/project/containers/templates/containers/_copy.html:16
+#: dashboards/project/containers/templates/containers/_create.html:16
+#: dashboards/project/containers/templates/containers/_upload.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/_create.html:16
+#: dashboards/project/networks/templates/networks/subnets/_create.html:17
+#: dashboards/project/volumes/forms.py:28
+#: dashboards/project/volumes/forms.py:195
+#: dashboards/project/volumes/tables.py:147
+#: dashboards/project/volumes/templates/volumes/_create.html:18
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:17
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:14
+msgid "Description"
+msgstr "Descrizione"
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:18
+msgid "From here you can define the sizing of a new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:24
+#: dashboards/admin/flavors/templates/flavors/_edit.html:25
+#: dashboards/admin/images/templates/images/_update.html:24
+#: dashboards/admin/networks/templates/networks/_create.html:24
+#: dashboards/admin/networks/templates/networks/_update.html:23
+#: dashboards/admin/networks/templates/networks/ports/_create.html:24
+#: dashboards/admin/networks/templates/networks/ports/_update.html:28
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:24
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:32
+#: dashboards/admin/projects/templates/projects/_add_user.html:24
+#: dashboards/admin/projects/templates/projects/_create.html:24
+#: dashboards/admin/projects/templates/projects/_create_user.html:24
+#: dashboards/admin/projects/templates/projects/_quotas.html:23
+#: dashboards/admin/projects/templates/projects/_update.html:24
+#: dashboards/admin/users/templates/users/_create.html:23
+#: dashboards/admin/users/templates/users/_update.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:32
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:20
+#: dashboards/project/containers/templates/containers/_copy.html:23
+#: dashboards/project/containers/templates/containers/_create.html:23
+#: dashboards/project/containers/templates/containers/_upload.html:24
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:32
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:24
+#: dashboards/project/instances/templates/instances/_update.html:23
+#: dashboards/project/networks/templates/networks/_create.html:23
+#: dashboards/project/networks/templates/networks/_update.html:23
+#: dashboards/project/networks/templates/networks/subnets/_create.html:24
+#: dashboards/project/networks/templates/networks/subnets/_update.html:32
+#: dashboards/project/volumes/templates/volumes/_attach.html:24
+#: dashboards/project/volumes/templates/volumes/_create.html:56
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:24
+#: dashboards/settings/ec2/templates/ec2/download_form.html:24
+#: dashboards/settings/project/templates/project/_openrc.html:31
+#: dashboards/settings/user/templates/user/_settings.html:24
+msgid "Cancel"
+msgstr "Annulla"
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:18
+msgid "From here you can alter the sizing of the current flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:19
+msgid ""
+"Note: this will not affect the resources allocated to any existing instances "
+"using this flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:24
+#: dashboards/admin/projects/workflows.py:270
+#: dashboards/settings/user/templates/user/_settings.html:23
+msgid "Save"
+msgstr "Salva"
+
+#: dashboards/admin/images/panel.py:29 dashboards/admin/images/tables.py:44
+#: dashboards/admin/images/templates/images/index.html:3
+#: dashboards/admin/images/templates/images/index.html:6
+#: dashboards/project/images_and_snapshots/images/tables.py:47
+#: dashboards/project/images_and_snapshots/images/tables.py:132
+msgid "Images"
+msgstr "Immagini"
+
+#: dashboards/admin/images/tables.py:40
+#: dashboards/project/images_and_snapshots/images/tables.py:113
+#: dashboards/project/instances/templates/instances/_detail_overview.html:74
+msgid "Image Name"
+msgstr "Nome Immagine"
+
+#: dashboards/admin/images/views.py:55
+msgid "Unable to retrieve image list."
+msgstr "Impossible recuperare lista immagini"
+
+#: dashboards/admin/images/templates/images/_update.html:8
+#: dashboards/admin/images/templates/images/_update.html:23
+#: dashboards/admin/images/templates/images/update.html:4
+#: dashboards/admin/images/templates/images/update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:22
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:6
+msgid "Update Image"
+msgstr "Aggiorna immagini"
+
+#: dashboards/admin/images/templates/images/_update.html:18
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:17
+msgid "From here you can modify different properties of an image."
+msgstr ""
+
+#: dashboards/admin/instances/panel.py:29
+#: dashboards/admin/instances/tables.py:94
+#: dashboards/admin/instances/templates/instances/index.html:3
+#: dashboards/admin/projects/workflows.py:40
+#: dashboards/project/instances/panel.py:25
+#: dashboards/project/instances/tables.py:70
+#: dashboards/project/instances/tables.py:90
+#: dashboards/project/instances/tables.py:107
+#: dashboards/project/instances/tables.py:136
+#: dashboards/project/instances/tables.py:313
+#: dashboards/project/instances/templates/instances/index.html:3
+#: dashboards/project/instances/templates/instances/index.html:6
+msgid "Instances"
+msgstr "Istanze"
+
+#: dashboards/admin/instances/tables.py:60 usage/tables.py:30
+msgid "Project Name"
+msgstr "Nome progetto."
+
+#: dashboards/admin/instances/tables.py:67
+#: dashboards/admin/services/tables.py:40
+msgid "Host"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:71
+#: dashboards/project/instances/tables.py:290
+#: dashboards/project/instances/workflows.py:176 usage/tables.py:57
+msgid "Instance Name"
+msgstr "Nome istanza"
+
+#: dashboards/admin/instances/tables.py:72
+#: dashboards/project/access_and_security/floating_ips/tables.py:111
+#: dashboards/project/access_and_security/floating_ips/workflows.py:32
+#: dashboards/project/access_and_security/floating_ips/workflows.py:39
+#: dashboards/project/instances/tables.py:291
+msgid "IP Address"
+msgstr "Indirizzo IP"
+
+#: dashboards/admin/instances/tables.py:74
+#: dashboards/project/containers/tables.py:256
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:30
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:37
+#: dashboards/project/instances/tables.py:293
+#: dashboards/project/volumes/tables.py:150
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:26
+msgid "Size"
+msgstr "Dimensione"
+
+#: dashboards/admin/instances/tables.py:79
+#: dashboards/admin/networks/tables.py:74
+#: dashboards/admin/networks/ports/tables.py:77
+#: dashboards/project/images_and_snapshots/images/tables.py:119
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:13
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:18
+#: dashboards/project/instances/tables.py:298
+#: dashboards/project/instances/templates/instances/_detail_overview.html:13
+#: dashboards/project/networks/tables.py:100
+#: dashboards/project/networks/ports/tables.py:44
+#: dashboards/project/networks/templates/networks/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:30
+#: dashboards/project/volumes/tables.py:154
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:17
+msgid "Status"
+msgstr "Stato"
+
+#: dashboards/admin/instances/tables.py:83
+#: dashboards/project/instances/tables.py:302
+msgid "Task"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:90
+#: dashboards/project/instances/tables.py:309
+msgid "Power State"
+msgstr "Stato alimentazione"
+
+#: dashboards/admin/instances/views.py:49
+#: dashboards/project/access_and_security/views.py:76
+#: dashboards/project/access_and_security/floating_ips/workflows.py:65
+msgid "Unable to retrieve instance list."
+msgstr "Impossible recuperare la lista delle istanze"
+
+#: dashboards/admin/instances/views.py:63
+#: dashboards/admin/networks/views.py:48
+msgid "Unable to retrieve instance tenant information."
+msgstr "Impossible recuperare informazioni tenant"
+
+#: dashboards/admin/instances/views.py:80
+#: dashboards/project/instances/views.py:82
+msgid "Unable to retrieve instance size information."
+msgstr "Impossibile recuperare informazioni sulle dimensioni dell'istanza"
+
+#: dashboards/admin/instances/templates/instances/index.html:6
+msgid "All Instances"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:36
+#: dashboards/admin/networks/tables.py:67
+#: dashboards/admin/projects/tables.py:65 dashboards/project/dashboard.py:40
+#: dashboards/project/instances/workflows.py:38
+msgid "Project"
+msgstr "Progetto"
+
+#: dashboards/admin/networks/forms.py:37 dashboards/admin/networks/forms.py:74
+#: dashboards/admin/networks/tables.py:72
+#: dashboards/project/networks/tables.py:98
+#: dashboards/project/networks/templates/networks/_detail_overview.html:17
+msgid "Shared"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:46 dashboards/admin/users/forms.py:42
+msgid "Select a project"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:58
+#, python-format
+msgid "Network %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:64
+#, python-format
+msgid "Failed to create network %s"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:71
+#: dashboards/admin/networks/templates/networks/ports/_update.html:12
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:12
+#: dashboards/admin/users/forms.py:114
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:11
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:12
+#: dashboards/project/instances/templates/instances/_detail_overview.html:11
+#: dashboards/project/networks/forms.py:39
+#: dashboards/project/networks/templates/networks/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_update.html:12
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:11
+msgid "ID"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:82
+#: dashboards/project/networks/forms.py:48
+#, python-format
+msgid "Network %s was successfully updated."
+msgstr "La rete %s è stata aggiornata correttamente."
+
+#: dashboards/admin/networks/forms.py:87
+#: dashboards/project/networks/forms.py:53
+#, python-format
+msgid "Failed to update network %s"
+msgstr ""
+
+#: dashboards/admin/networks/panel.py:25
+#: dashboards/admin/networks/tables.py:35
+#: dashboards/admin/networks/tables.py:80
+#: dashboards/admin/networks/templates/networks/index.html:3
+#: dashboards/admin/networks/templates/networks/index.html:6
+#: dashboards/project/instances/workflows.py:412
+#: dashboards/project/networks/panel.py:25
+#: dashboards/project/networks/tables.py:44
+#: dashboards/project/networks/tables.py:106
+#: dashboards/project/networks/templates/networks/index.html:3
+#: dashboards/project/networks/templates/networks/index.html:6
+msgid "Networks"
+msgstr "Reti"
+
+#: dashboards/admin/networks/tables.py:34
+#: dashboards/project/networks/tables.py:43
+#: dashboards/project/networks/templates/networks/subnets/index.html:3
+#: dashboards/project/networks/templates/networks/subnets/index.html:6
+msgid "Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:41
+#: dashboards/project/networks/tables.py:59
+#, python-format
+msgid "Failed to delete network %s"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:49
+#: dashboards/admin/networks/templates/networks/_create.html:8
+#: dashboards/admin/networks/templates/networks/_create.html:23
+#: dashboards/admin/networks/templates/networks/create.html:3
+#: dashboards/admin/networks/templates/networks/create.html:6
+#: dashboards/project/networks/tables.py:67
+#: dashboards/project/networks/workflows.py:111
+#: dashboards/project/networks/templates/networks/_create.html:7
+#: dashboards/project/networks/templates/networks/_create.html:22
+#: dashboards/project/networks/templates/networks/create.html:3
+#: dashboards/project/networks/templates/networks/create.html:6
+msgid "Create Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:56
+#: dashboards/admin/networks/templates/networks/_update.html:7
+#: dashboards/project/networks/tables.py:74
+#: dashboards/project/networks/templates/networks/_update.html:7
+msgid "Edit Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:68
+#: dashboards/admin/networks/ports/forms.py:33
+#: dashboards/project/networks/subnets/forms.py:35
+msgid "Network Name"
+msgstr "Nome della rete"
+
+#: dashboards/admin/networks/tables.py:71
+#: dashboards/project/networks/tables.py:97
+msgid "Subnets Associated"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:76
+#: dashboards/admin/networks/ports/tables.py:79
+#: dashboards/project/networks/tables.py:102
+#: dashboards/project/networks/ports/tables.py:46
+#: dashboards/project/networks/templates/networks/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:32
+msgid "Admin State"
+msgstr ""
+
+#: dashboards/admin/networks/views.py:60
+#: dashboards/project/networks/views.py:52
+msgid "Network list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:91
+#: dashboards/project/networks/views.py:109
+msgid "Subnet list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:103
+#: dashboards/project/networks/views.py:121
+msgid "Port list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:118
+#: dashboards/project/networks/views.py:134
+#: dashboards/project/networks/subnets/tables.py:96
+#, python-format
+msgid "Unable to retrieve details for network \"%s\"."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:36
+#: dashboards/project/networks/subnets/forms.py:39
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:13
+msgid "Network ID"
+msgstr "ID della rete"
+
+#: dashboards/admin/networks/ports/forms.py:42
+#: dashboards/admin/networks/ports/forms.py:74
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:34
+msgid "Device ID"
+msgstr "ID dispositivo"
+
+#: dashboards/admin/networks/ports/forms.py:54
+#, python-format
+msgid "Port %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:59
+#, python-format
+msgid "Failed to create a port for network %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:84
+#, python-format
+msgid "Port %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:89
+#, python-format
+msgid "Failed to update port %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:34
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:6
+msgid "Port"
+msgstr "Porta"
+
+#: dashboards/admin/networks/ports/tables.py:35
+#: dashboards/admin/networks/ports/tables.py:83
+#: dashboards/project/networks/ports/tables.py:53
+msgid "Ports"
+msgstr "Porte"
+
+#: dashboards/admin/networks/ports/tables.py:41
+#: dashboards/admin/networks/subnets/tables.py:39
+#: dashboards/project/networks/subnets/tables.py:51
+#, python-format
+msgid "Failed to delete subnet %s"
+msgstr "Eliminazione della sottorete %s fallita"
+
+#: dashboards/admin/networks/ports/tables.py:51
+#: dashboards/admin/networks/templates/networks/ports/_create.html:8
+#: dashboards/admin/networks/templates/networks/ports/_create.html:23
+#: dashboards/admin/networks/templates/networks/ports/create.html:3
+#: dashboards/admin/networks/templates/networks/ports/create.html:6
+msgid "Create Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:62
+#: dashboards/admin/networks/templates/networks/ports/_update.html:7
+msgid "Edit Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:75
+#: dashboards/project/networks/ports/tables.py:42
+msgid "Fixed IPs"
+msgstr "Indirizzo IP fisso"
+
+#: dashboards/admin/networks/ports/tables.py:76
+#: dashboards/project/networks/ports/tables.py:43
+msgid "Device Attached"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tabs.py:32
+#: dashboards/admin/overview/panel.py:29
+#: dashboards/admin/overview/templates/overview/usage.html:6
+#: dashboards/project/images_and_snapshots/images/tabs.py:27
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:27
+#: dashboards/project/instances/tabs.py:26
+#: dashboards/project/networks/ports/tabs.py:32
+#: dashboards/project/networks/subnets/tabs.py:32
+#: dashboards/project/overview/panel.py:29
+#: dashboards/project/overview/templates/overview/usage.html:6
+#: dashboards/project/volumes/tabs.py:27
+msgid "Overview"
+msgstr "Sommario"
+
+#: dashboards/admin/networks/ports/tabs.py:42
+#: dashboards/project/networks/ports/tabs.py:42
+msgid "Unable to retrieve port details."
+msgstr "Impossible recuperare informazioni sulle porte"
+
+#: dashboards/admin/networks/ports/views.py:49
+#: dashboards/admin/networks/subnets/views.py:49
+#: dashboards/project/networks/subnets/views.py:54
+msgid "Unable to retrieve network."
+msgstr "Impossible recuperare rete."
+
+#: dashboards/admin/networks/ports/views.py:82
+msgid "Unable to retrieve port details"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/forms.py:43
+#, python-format
+msgid "Failed to retrieve network %s for a subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:32
+#: dashboards/project/networks/subnets/tables.py:44
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:6
+msgid "Subnet"
+msgstr "Sottorete"
+
+#: dashboards/admin/networks/subnets/tables.py:33
+#: dashboards/admin/networks/subnets/tables.py:81
+#: dashboards/project/networks/subnets/tables.py:45
+#: dashboards/project/networks/subnets/tables.py:104
+msgid "Subnets"
+msgstr "Sottoreti"
+
+#: dashboards/admin/networks/subnets/tables.py:49
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:8
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:23
+#: dashboards/admin/networks/templates/networks/subnets/create.html:3
+#: dashboards/admin/networks/templates/networks/subnets/create.html:6
+#: dashboards/project/networks/workflows.py:53
+#: dashboards/project/networks/subnets/tables.py:61
+#: dashboards/project/networks/templates/networks/subnets/_create.html:8
+#: dashboards/project/networks/templates/networks/subnets/_create.html:23
+#: dashboards/project/networks/templates/networks/subnets/create.html:3
+#: dashboards/project/networks/templates/networks/subnets/create.html:6
+msgid "Create Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:60
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:7
+#: dashboards/project/networks/subnets/tables.py:72
+#: dashboards/project/networks/templates/networks/subnets/_update.html:7
+msgid "Edit Subnet"
+msgstr "Modifica sottorete"
+
+#: dashboards/admin/networks/subnets/tables.py:72
+#: dashboards/project/access_and_security/security_groups/forms.py:91
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:15
+msgid "CIDR"
+msgstr "CIDR"
+
+#: dashboards/admin/networks/subnets/tables.py:73
+#: dashboards/project/networks/workflows.py:66
+#: dashboards/project/networks/subnets/forms.py:53
+#: dashboards/project/networks/subnets/tables.py:85
+msgid "IP Version"
+msgstr "Versione protocollo IP"
+
+#: dashboards/admin/networks/subnets/tables.py:74
+#: dashboards/project/networks/subnets/forms.py:54
+#: dashboards/project/networks/subnets/forms.py:104
+#: dashboards/project/networks/subnets/tables.py:86
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:19
+msgid "Gateway IP"
+msgstr "Indirizzo IP del Gateway"
+
+#: dashboards/admin/networks/subnets/views.py:82
+#: dashboards/project/networks/subnets/views.py:86
+msgid "Unable to retrieve subnet details"
+msgstr "Impossible recuperare dettagli rete"
+
+#: dashboards/admin/networks/templates/networks/_create.html:18
+#: dashboards/project/networks/templates/networks/_create.html:17
+msgid "Select a name for your network."
+msgstr "Specifica un nome per la tua rete."
+
+#: dashboards/admin/networks/templates/networks/_update.html:16
+#: dashboards/admin/networks/templates/networks/ports/_update.html:21
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:25
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:17
+#: dashboards/project/instances/templates/instances/_update.html:16
+#: dashboards/project/networks/templates/networks/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_update.html:25
+#: dashboards/settings/ec2/templates/ec2/download_form.html:17
+#: dashboards/settings/project/templates/project/_openrc.html:24
+#: dashboards/settings/user/templates/user/_settings.html:17
+msgid "Description:"
+msgstr "Descrizione:"
+
+#: dashboards/admin/networks/templates/networks/_update.html:17
+#: dashboards/project/networks/templates/networks/_update.html:17
+msgid "You may update the editable properties of your network here."
+msgstr "Puoi aggiornare le proprietà modificabili della tua rete qui."
+
+#: dashboards/admin/networks/templates/networks/_update.html:22
+#: dashboards/admin/networks/templates/networks/ports/_update.html:27
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:31
+#: dashboards/project/instances/templates/instances/_update.html:22
+#: dashboards/project/networks/templates/networks/_update.html:22
+#: dashboards/project/networks/templates/networks/subnets/_update.html:31
+msgid "Save Changes"
+msgstr "Salva modifiche."
+
+#: dashboards/admin/networks/templates/networks/update.html:3
+#: dashboards/admin/networks/templates/networks/update.html:6
+#: dashboards/project/networks/templates/networks/update.html:3
+#: dashboards/project/networks/templates/networks/update.html:6
+msgid "Update Network"
+msgstr "Aggiorna rete"
+
+#: dashboards/admin/networks/templates/networks/ports/_create.html:18
+msgid ""
+"You can create a port for the network. If you specify device ID to be "
+"attached, the device specified will be attached to the port created."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_update.html:22
+msgid "You may update the editable properties of your port here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/update.html:3
+#: dashboards/admin/networks/templates/networks/ports/update.html:6
+msgid "Update Port"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:18
+#: dashboards/project/networks/templates/networks/subnets/_create.html:18
+msgid ""
+"You can create a subnet for the network. Any network address can be "
+"specified unless the network address does not overlap other subnets in the "
+"network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:14
+#: dashboards/project/networks/workflows.py:58
+#: dashboards/project/networks/subnets/forms.py:45
+#: dashboards/project/networks/subnets/tables.py:84
+#: dashboards/project/networks/templates/networks/subnets/_update.html:14
+msgid "Network Address"
+msgstr "Indirizzo di rete"
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:17
+#: dashboards/project/networks/templates/networks/subnets/_update.html:16
+msgid "IP version"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:26
+#: dashboards/project/networks/templates/networks/subnets/_update.html:26
+msgid "You may update the editable properties of your subnet here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/index.html:3
+#: dashboards/admin/networks/templates/networks/subnets/index.html:6
+#: dashboards/project/networks/templates/networks/detail.html:3
+msgid "Network Detail"
+msgstr "Dettagli rete."
+
+#: dashboards/admin/networks/templates/networks/subnets/update.html:3
+#: dashboards/admin/networks/templates/networks/subnets/update.html:6
+#: dashboards/project/networks/templates/networks/subnets/update.html:3
+#: dashboards/project/networks/templates/networks/subnets/update.html:6
+msgid "Update Subnet"
+msgstr ""
+
+#: dashboards/admin/overview/templates/overview/usage.html:3
+msgid "Usage Overview"
+msgstr "Riepilogo Utilizzo"
+
+#: dashboards/admin/overview/templates/overview/usage.html:12
+msgid "Monitoring"
+msgstr ""
+
+#: dashboards/admin/projects/panel.py:29
+#: dashboards/admin/projects/tables.py:66
+#: dashboards/admin/projects/tables.py:95
+#: dashboards/admin/projects/templates/projects/index.html:8
+#: templates/403.html:24 templates/404.html:23 templates/500.html:23
+msgid "Projects"
+msgstr "Progetti"
+
+#: dashboards/admin/projects/tables.py:19
+msgid "Modify Users"
+msgstr "Modifica utenti"
+
+#: dashboards/admin/projects/tables.py:32
+msgid "View Usage"
+msgstr "Visualizza utilizzo"
+
+#: dashboards/admin/projects/tables.py:39
+#: dashboards/admin/projects/templates/projects/_create.html:8
+#: dashboards/admin/projects/templates/projects/_create.html:23
+#: dashboards/admin/projects/templates/projects/create.html:6
+msgid "Create Project"
+msgstr "Crea Progetto"
+
+#: dashboards/admin/projects/tables.py:46
+#: dashboards/admin/projects/workflows.py:269
+#: dashboards/admin/projects/templates/projects/update.html:3
+#: dashboards/admin/projects/templates/projects/update.html:6
+msgid "Edit Project"
+msgstr "Modifica projetto"
+
+#: dashboards/admin/projects/tables.py:90
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:60
+#: dashboards/project/networks/templates/networks/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:15
+msgid "Project ID"
+msgstr "ID progetto"
+
+#: dashboards/admin/projects/tables.py:91
+#: dashboards/admin/projects/workflows.py:76
+#: dashboards/admin/projects/workflows.py:251
+#: dashboards/admin/services/tables.py:42 dashboards/admin/users/tables.py:40
+#: dashboards/admin/users/tables.py:115
+msgid "Enabled"
+msgstr "Abilitato"
+
+#: dashboards/admin/projects/tables.py:104
+msgid "Remove"
+msgstr "Rimuovi"
+
+#: dashboards/admin/projects/tables.py:105
+msgid "Removed"
+msgstr "Rimosso"
+
+#: dashboards/admin/projects/tables.py:106 dashboards/admin/users/tables.py:41
+#: dashboards/admin/users/tables.py:75
+#: dashboards/project/instances/workflows.py:39
+msgid "User"
+msgstr "Utente"
+
+#: dashboards/admin/projects/tables.py:107 dashboards/admin/users/panel.py:29
+#: dashboards/admin/users/tables.py:42 dashboards/admin/users/tables.py:76
+#: dashboards/admin/users/tables.py:122
+#: dashboards/admin/users/templates/users/index.html:8
+msgid "Users"
+msgstr "Utenti"
+
+#: dashboards/admin/projects/tables.py:125
+msgid "Unable to retrieve role information."
+msgstr "Impossible recuperare informazioni sul ruolo."
+
+#: dashboards/admin/projects/tables.py:130
+msgid "Roles"
+msgstr "Ruoli"
+
+#: dashboards/admin/projects/tables.py:134
+msgid "Users For Project"
+msgstr "Utenti per progetto"
+
+#: dashboards/admin/projects/tables.py:142
+msgid "Add To Project"
+msgstr "Aggiungi al progetto"
+
+#: dashboards/admin/projects/tables.py:154
+msgid "Add New Users"
+msgstr "Aggiungi nuovi utenti"
+
+#: dashboards/admin/projects/views.py:67
+msgid "Unable to retrieve project information."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:87
+msgid "Unable to retrieve project list."
+msgstr "Impossibile recuperare lista progetti"
+
+#: dashboards/admin/projects/views.py:110
+msgid "Unable to retrieve users."
+msgstr "Impossibile recuperare utenti"
+
+#: dashboards/admin/projects/views.py:154
+msgid "Unable to retrieve default quota values."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:182
+msgid "Unable to retrieve project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:37
+msgid "Injected File Content Bytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:38
+msgid "Metadata Items"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:41
+msgid "Injected Files"
+msgstr "Files iniettati"
+
+#: dashboards/admin/projects/workflows.py:44
+#: dashboards/admin/volumes/panel.py:9 dashboards/admin/volumes/tables.py:15
+#: dashboards/admin/volumes/templates/volumes/index.html:3
+#: dashboards/admin/volumes/templates/volumes/index.html:6
+#: dashboards/project/volumes/panel.py:25
+#: dashboards/project/volumes/tables.py:38
+#: dashboards/project/volumes/tables.py:171
+#: dashboards/project/volumes/tables.py:183
+#: dashboards/project/volumes/templates/volumes/index.html:3
+#: dashboards/project/volumes/templates/volumes/index.html:6
+msgid "Volumes"
+msgstr "Volumi"
+
+#: dashboards/admin/projects/workflows.py:45
+msgid "Gigabytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:46
+msgid "RAM (MB)"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:47
+#: dashboards/project/access_and_security/floating_ips/tables.py:50
+#: dashboards/project/access_and_security/floating_ips/tables.py:128
+msgid "Floating IPs"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:50
+msgid "Quota"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:52
+msgid "From here you can set quotas (max limits) for the project."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:81
+#: dashboards/admin/projects/workflows.py:254
+msgid "Project Info"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:82
+#: dashboards/admin/projects/templates/projects/_create.html:18
+msgid "From here you can create a new project to organize users."
+msgstr "Da qui puoi creare un nuovo progetto per organizzare gli utenti."
+
+#: dashboards/admin/projects/workflows.py:101
+msgid "Unable to retrieve user list. Please try again later."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:155
+#: dashboards/admin/projects/templates/projects/_update_members.html:16
+msgid "Project Members"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:169
+#: dashboards/admin/users/views.py:47
+msgid "Unable to retrieve user list."
+msgstr "Impossible recuperare lista utenti"
+
+#: dashboards/admin/projects/workflows.py:180
+msgid "Add Project"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:181
+msgid "Finish"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:182
+#, python-format
+msgid "Created new project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:183
+#, python-format
+msgid "Unable to create project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:227
+#, python-format
+msgid "Failed to add %s project members and set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:246
+msgid "Unable to set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:256
+msgid "From here you can edit the project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:271
+#, python-format
+msgid "Modified project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:272
+#, python-format
+msgid "Unable to modify project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:342
+#, python-format
+msgid "Failed to modify %s project members and update project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:363
+msgid ""
+"Modified project information and members, but unable to modify project "
+"quotas."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:8
+#: dashboards/admin/projects/templates/projects/add_user.html:3
+#: dashboards/admin/projects/templates/projects/add_user.html:6
+msgid "Add User To Project"
+msgstr "Aggiungi utente a progetto"
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:18
+msgid "Select the user role for the project."
+msgstr "Seleziona il ruolo utente per il progetto."
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:23
+msgid "Add"
+msgstr "Aggiungi"
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:7
+#, python-format
+msgid "Create User for project '%(tenant_name)s'."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:18
+msgid "From here you can create a new user to add to this project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:23
+#: dashboards/admin/users/tables.py:20
+#: dashboards/admin/users/templates/users/_create.html:7
+#: dashboards/admin/users/templates/users/_create.html:22
+#: dashboards/admin/users/templates/users/create.html:7
+msgid "Create User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:7
+#: dashboards/admin/projects/templates/projects/_quotas.html:22
+msgid "Update Quota"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:17
+#, python-format
+msgid ""
+"From here you can edit quotas (max limits) for the project %(tenant.name)s."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update.html:8
+#: dashboards/admin/projects/templates/projects/_update.html:23
+#: dashboards/admin/projects/templates/projects/quotas.html:6
+msgid "Update Project"
+msgstr "Aggiorna progetto"
+
+#: dashboards/admin/projects/templates/projects/_update.html:18
+msgid "From here you can edit a project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:7
+msgid ""
+"From here you can add and remove members to this project from the list of "
+"all available users."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:10
+msgid "All Users"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:25
+#: dashboards/admin/projects/templates/projects/_update_members.html:32
+msgid "No users found."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/create_user.html:3
+#: dashboards/admin/projects/templates/projects/create_user.html:6
+msgid "Add New User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:3
+msgid "Project Usage Overview"
+msgstr "Riepilogo utilizzo progetto"
+
+#: dashboards/admin/projects/templates/projects/usage.html:7
+msgid "Project Usage"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/users.html:7
+msgid "Users for Project"
+msgstr ""
+
+#: dashboards/admin/quotas/panel.py:29 dashboards/admin/quotas/tables.py:36
+msgid "Quotas"
+msgstr ""
+
+#: dashboards/admin/quotas/tables.py:28
+msgid "Quota Name"
+msgstr ""
+
+#: dashboards/admin/quotas/tables.py:29
+msgid "Limit"
+msgstr ""
+
+#: dashboards/admin/quotas/views.py:46
+msgid "Unable to get quota info."
+msgstr ""
+
+#: dashboards/admin/quotas/templates/quotas/index.html:8
+msgid "Default Quotas"
+msgstr ""
+
+#: dashboards/admin/services/panel.py:29
+#: dashboards/admin/services/tables.py:47
+#: dashboards/admin/services/templates/services/index.html:8
+msgid "Services"
+msgstr ""
+
+#: dashboards/admin/services/tables.py:37
+msgid "Id"
+msgstr ""
+
+#: dashboards/admin/services/tables.py:39
+msgid "Service"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:54
+msgid "Passwords do not match."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:62 dashboards/admin/users/forms.py:115
+#: dashboards/admin/users/tables.py:108
+msgid "User Name"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:63 dashboards/admin/users/forms.py:116
+#: dashboards/admin/users/tables.py:109
+msgid "Email"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:65 dashboards/admin/users/forms.py:117
+msgid "Password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:70 dashboards/admin/users/forms.py:124
+msgid "Confirm Password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:73 dashboards/admin/users/forms.py:127
+msgid "Primary Project"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:75
+msgid "Role"
+msgstr "Ruolo"
+
+#: dashboards/admin/users/forms.py:96
+#, python-format
+msgid "User \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:106
+msgid "Unable to add userto primary project."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:110
+msgid "Unable to create user."
+msgstr "Impossible creare utente"
+
+#: dashboards/admin/users/forms.py:151
+msgid "name"
+msgstr "Nome"
+
+#: dashboards/admin/users/forms.py:151
+msgid "email"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:160
+msgid "primary project"
+msgstr "Progetto principale"
+
+#: dashboards/admin/users/forms.py:173
+#, python-format
+msgid "The user %s has no role defined for"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:181
+msgid "password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:190
+msgid "User has been updated successfully."
+msgstr "L'utente è stato correttamente aggiornato."
+
+#: dashboards/admin/users/forms.py:194
+#, python-format
+msgid "Unable to update %(attributes)s for the user."
+msgstr "Impossibile aggiornare %(attributes)s per l'utente"
+
+#: dashboards/admin/users/tables.py:32
+#: dashboards/project/images_and_snapshots/images/tables.py:68
+msgid "Edit"
+msgstr "Modifica"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Enable"
+msgstr "Abilita"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Disable"
+msgstr "Disabilita"
+
+#: dashboards/admin/users/tables.py:40
+msgid "Disabled"
+msgstr "Disabilitato"
+
+#: dashboards/admin/users/tables.py:63
+msgid "You cannot disable the user you are currently logged in as."
+msgstr ""
+"Impossibile disabilitare l'utente con cui si e' correntemente collegati"
+
+#: dashboards/admin/users/tables.py:114
+msgid "User ID"
+msgstr "ID utente"
+
+#: dashboards/admin/users/views.py:70
+msgid "Unable to update user."
+msgstr "Impossibile aggiornare utente"
+
+#: dashboards/admin/users/views.py:104
+msgid "Unable to retrieve user roles."
+msgstr "Impossibile recuperare ruoli utente"
+
+#: dashboards/admin/users/templates/users/_create.html:17
+msgid "From here you can create a new user and assign them to a project."
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_update.html:7
+#: dashboards/admin/users/templates/users/_update.html:22
+#: dashboards/admin/users/templates/users/update.html:7
+msgid "Update User"
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_update.html:17
+msgid ""
+"From here you can edit the user's details, including their default project."
+msgstr ""
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:3
+#: dashboards/project/volumes/templates/volumes/detail.html:3
+msgid "Volume Details"
+msgstr "Dettagli Volume"
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:6
+#: dashboards/project/volumes/templates/volumes/detail.html:6
+msgid "Volume Detail"
+msgstr "Dettagli Volume"
+
+#: dashboards/project/dashboard.py:24
+msgid "Manage Compute"
+msgstr "Gestisci \"Compute\""
+
+#: dashboards/project/dashboard.py:35
+msgid "Object Store"
+msgstr ""
+
+#: dashboards/project/access_and_security/panel.py:26
+#: dashboards/project/instances/workflows.py:348
+msgid "Access & Security"
+msgstr "Accesso e Sicurezza"
+
+#: dashboards/project/access_and_security/views.py:51
+msgid "Unable to retrieve keypair list."
+msgstr "Impossibile recuperare la lista di keypair"
+
+#: dashboards/project/access_and_security/views.py:60
+#: dashboards/project/access_and_security/security_groups/views.py:74
+msgid "Unable to retrieve security groups."
+msgstr "Impossible recuperare Security Groups"
+
+#: dashboards/project/access_and_security/views.py:69
+#: dashboards/project/access_and_security/floating_ips/workflows.py:49
+msgid "Unable to retrieve floating IP addresses."
+msgstr "Impossible recuperare indirizzo del Floating IP"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:32
+msgid "Pool"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:43
+#, python-format
+msgid "Allocated Floating IP %(ip)s."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:47
+msgid "Unable to allocate Floating IP."
+msgstr "Impossible assegnare Floating IP"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:37
+msgid "Allocate IP To Project"
+msgstr "Assegna un IP al progetto"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:47
+msgid "Release"
+msgstr "Rilascia"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:48
+msgid "Released"
+msgstr "Rilasciato"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:49
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:22
+msgid "Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:6
+#: dashboards/project/instances/tables.py:219
+msgid "Associate Floating IP"
+msgstr "Associa un 'Floating IP'"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:76
+msgid "Disassociate Floating IP"
+msgstr "Dissocia Floating IP"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:90
+#, python-format
+msgid "Successfully disassociated Floating IP: %s"
+msgstr "Floating IP:%s dissociato correttamente"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:94
+msgid "Unable to disassociate floating IP."
+msgstr "Impossible dissociare Floating IP"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:114
+#: dashboards/project/access_and_security/floating_ips/workflows.py:36
+#: dashboards/project/instances/tables.py:69
+#: dashboards/project/instances/tables.py:89
+#: dashboards/project/instances/tables.py:106
+#: dashboards/project/instances/tables.py:135
+#: dashboards/project/volumes/tables.py:206
+msgid "Instance"
+msgstr "Istanza"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:117
+msgid "Floating IP Pool"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:65
+msgid "Unable to retrieve floating IP pools."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:68
+msgid "No floating IP pools available."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:40
+msgid "Select the IP address you wish to associate with the selected instance."
+msgstr "Specifica l'indirizzo IP che vuoi associare all'istanza selezionata."
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:53
+msgid "Select an IP address"
+msgstr "Seleziona un indirizzo IP."
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:55
+msgid "No IP addresses available"
+msgstr "Nessun indirizzo IP disponibile."
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:76
+#: dashboards/project/volumes/forms.py:160
+msgid "Select an instance"
+msgstr "Seleziona un istanza"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:78
+#: dashboards/project/volumes/forms.py:162
+msgid "No instances available"
+msgstr "Nessuna istanza disponibile"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:97
+msgid "Manage Floating IP Associations"
+msgstr "Gestisci associazioni con Floating IP"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:98
+msgid "Associate"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:99
+#, python-format
+msgid "IP address %s associated."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:100
+#, python-format
+msgid "Unable to associate IP address %s."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:38
+#: dashboards/project/access_and_security/keypairs/forms.py:49
+#: dashboards/project/access_and_security/keypairs/tables.py:52
+msgid "Keypair Name"
+msgstr "Nome del keypair"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:40
+msgid ""
+"Keypair names may only contain letters, numbers, underscores and hyphens."
+msgstr ""
+"I nomi dei keypair possono contenere solo lettere, numeri, underscores e "
+"trattini"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:51
+msgid "Public Key"
+msgstr "Chiave pubblica"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:60
+#, python-format
+msgid "Successfully imported public key: %s"
+msgstr "Chiave pubblica importata correttamente: %s"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:65
+msgid "Unable to import keypair."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:30
+#: dashboards/project/instances/tables.py:295
+#: dashboards/project/instances/workflows.py:335
+msgid "Keypair"
+msgstr "Keypair"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:31
+#: dashboards/project/access_and_security/keypairs/tables.py:60
+msgid "Keypairs"
+msgstr "Keypairs"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:39
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html:6
+msgid "Import Keypair"
+msgstr "Importa Keypair"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:46
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html:6
+msgid "Create Keypair"
+msgstr "Crea Keypair"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:53
+msgid "Fingerprint"
+msgstr "Fingerprint"
+
+#: dashboards/project/access_and_security/keypairs/views.py:74
+#, python-format
+msgid "Unable to create keypair: %(exc)s"
+msgstr "Impossible create Keypair: %(exc)s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:46
+#, python-format
+msgid "Successfully created security group: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:52
+msgid "Unable to create security group."
+msgstr "Impossible creare 'Security Group'"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:57
+#: dashboards/project/access_and_security/security_groups/tables.py:93
+msgid "IP Protocol"
+msgstr "Protocollo IP"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:61
+msgid "The protocol which this rule should be applied to."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:65
+#: dashboards/project/access_and_security/security_groups/forms.py:71
+#: dashboards/project/access_and_security/security_groups/tables.py:95
+msgid "From Port"
+msgstr "Dal porto"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:66
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP type in the range (-1: 255)"
+msgstr ""
+"TCP/UDP: Inserire valori interi compresi tra 1 e 65535. ICMP: inserire un "
+"valore per il tipo ICMP nell'intervallo (-1:255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:72
+#: dashboards/project/images_and_snapshots/images/tables.py:115
+msgid "Type"
+msgstr "Tipo"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:74
+#: dashboards/project/access_and_security/security_groups/forms.py:80
+#: dashboards/project/access_and_security/security_groups/tables.py:96
+msgid "To Port"
+msgstr "Al porto"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:75
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP code in the range (-1: 255)"
+msgstr ""
+"TCP/UDP: Inserire valori interi compresi tra 1 e 65535. ICMP: inserire un "
+"valore per il tipo ICMP nell'intervallo (-1:255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:81
+msgid "Code"
+msgstr "Codice"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:84
+msgid "Source Group"
+msgstr "Gruppo di origine"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:86
+msgid ""
+"To specify an allowed IP range, select CIDR. To allow access from all "
+"members of another security group select Source Group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:94
+msgid "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:121
+msgid "The ICMP type is invalid."
+msgstr "Tipo ICMP non valido."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:124
+msgid "The ICMP code is invalid."
+msgstr "Codice ICMP non valido."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:127
+msgid "The ICMP type not in range (-1, 255)"
+msgstr "Tipo ICMP al di fuori dell'intervallo (-1, 255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:130
+msgid "The ICMP code not in range (-1, 255)"
+msgstr "Codice ICMP al di fuori dell'intervallo (-1, 255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:134
+msgid "The \"from\" port number is invalid."
+msgstr "Il numero della porta di origine non è valido."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:137
+msgid "The \"to\" port number is invalid."
+msgstr "Il numero della porta di destinazione non è valido."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:140
+msgid ""
+"The \"to\" port number must be greater than or equal to the \"from\" port "
+"number."
+msgstr ""
+"Il numero della porta di destinazione deve essere maggiore o uguale del "
+"numero della porta di origine"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:146
+msgid "Either CIDR or Source Group may be specified, but not both."
+msgstr "CIDR o gruppo di origini possono essere specificati, ma non entrambi"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:168
+#, python-format
+msgid "Successfully added rule: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:173
+msgid "Unable to add rule to security group."
+msgstr "Impossible aggiungere regola al security group."
+
+#: dashboards/project/access_and_security/security_groups/tables.py:31
+msgid "Security Group"
+msgstr "Security Group"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:32
+#: dashboards/project/access_and_security/security_groups/tables.py:66
+#: dashboards/project/instances/workflows.py:340
+#: dashboards/project/instances/templates/instances/_detail_overview.html:49
+msgid "Security Groups"
+msgstr "Security Groups"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:45
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html:6
+msgid "Create Security Group"
+msgstr "Creare un Security Group"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:52
+msgid "Edit Rules"
+msgstr "Modifica regole"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:72
+msgid "Rule"
+msgstr "Regola"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:73
+msgid "Rules"
+msgstr "Regole"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:97
+msgid "Source"
+msgstr "Sorgente"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:107
+msgid "Security Group Rules"
+msgstr "Regole dei Security Groups"
+
+#: dashboards/project/access_and_security/security_groups/views.py:60
+msgid "Unable to retrieve security group."
+msgstr "Impossible recuperare Security Groups"
+
+#: dashboards/project/access_and_security/security_groups/views.py:80
+#, python-format
+msgid "%s (current)"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/index.html:6
+msgid "Access &amp; Security"
+msgstr "Accesso e Sicurezza"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:8
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html:3
+msgid "Allocate Floating IP"
+msgstr "Alloca un 'Floating IP'"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:18
+msgid "Allocate a floating IP from a given floating ip pool."
+msgstr "Alloca un floating IP da uno specifico gruppo."
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:20
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:19
+msgid "Project Quotas"
+msgstr "Quote per i progetti"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:31
+msgid "Allocate IP"
+msgstr "Assegna IP"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:17
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:17
+msgid ""
+"Keypairs are ssh credentials which are injected into images when they are "
+"launched. Creating a new key pair registers the public key and downloads the "
+"private key (a .pem file)."
+msgstr ""
+"I keypairs sono credenziali ssh che vengono iniettate nell immagini durante "
+"l'avvio. Alla creazione di un nuovo key pair, la chiave pubblica viene "
+"registrata e la chiave privata scaricata (in un file .pem)"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:18
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:18
+msgid "Protect and use the key as you would any normal ssh private key."
+msgstr "Proteggi ed usa la chiave come faresti con una qualsiasi chiave ssh."
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:6
+msgid "Download Keypair"
+msgstr "Scarica keypair."
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:11
+#, python-format
+msgid ""
+"The keypair &quot;%(keypair_name)s&quot; should download automatically. If "
+"not use the link below."
+msgstr ""
+"Il keypair &quot;%(keypair_name)s&quot; dovrebbe essere scaricato "
+"automaticamente. In caso contrario, utilizzare il collegamento sottostante."
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:15
+#, python-format
+msgid "Download keypair &quot;%(keypair_name)s&quot;"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:18
+msgid "From here you can create a new security group"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:9
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html:6
+msgid "Edit Security Group Rules"
+msgstr "Modifica regole per il 'Security Group'"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:12
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:19
+msgid "Add Rule"
+msgstr "Aggiungi una regola"
+
+#: dashboards/project/containers/browsers.py:26
+msgid "Swift"
+msgstr ""
+
+#: dashboards/project/containers/browsers.py:29
+#: dashboards/project/containers/tables.py:40
+msgid "Container"
+msgstr "Container"
+
+#: dashboards/project/containers/forms.py:39
+msgid "Slash is not an allowed character."
+msgstr "la slash non è un carattere utilizzabile"
+
+#: dashboards/project/containers/forms.py:49
+#: dashboards/project/containers/tables.py:121
+msgid "Container Name"
+msgstr "Nome del container"
+
+#: dashboards/project/containers/forms.py:57
+msgid "Container created successfully."
+msgstr "Container creato con successo"
+
+#: dashboards/project/containers/forms.py:68
+msgid "Folder created successfully."
+msgstr "Cartella creata correttamente."
+
+#: dashboards/project/containers/forms.py:71
+msgid "Unable to create container."
+msgstr "Impossibile creare il container"
+
+#: dashboards/project/containers/forms.py:79
+#: dashboards/project/containers/tables.py:253
+msgid "Object Name"
+msgstr "Nome dell' oggetto"
+
+#: dashboards/project/containers/forms.py:81
+msgid "File"
+msgstr "File"
+
+#: dashboards/project/containers/forms.py:95
+msgid "Object was successfully uploaded."
+msgstr "Oggetto caricato con successo"
+
+#: dashboards/project/containers/forms.py:98
+msgid "Unable to upload object."
+msgstr "Impossibile caricare l' oggetto"
+
+#: dashboards/project/containers/forms.py:102
+msgid "Destination container"
+msgstr "Container di destinazione"
+
+#: dashboards/project/containers/forms.py:106
+msgid "Destination object name"
+msgstr "Nome dell' oggetto di destinazione"
+
+#: dashboards/project/containers/forms.py:137
+#: dashboards/project/containers/forms.py:163
+msgid "Unable to copy object."
+msgstr "Impossibile copiare l' oggetto"
+
+#: dashboards/project/containers/forms.py:153
+#, python-format
+msgid "Copied \"%(orig)s\" to \"%(dest)s\" as \"%(new)s\"."
+msgstr ""
+
+#: dashboards/project/containers/panel.py:29
+#: dashboards/project/containers/tables.py:41
+#: dashboards/project/containers/tables.py:128
+#: dashboards/project/containers/templates/containers/index.html:7
+msgid "Containers"
+msgstr "Containers"
+
+#: dashboards/project/containers/tables.py:62
+#: dashboards/project/containers/templates/containers/_create.html:7
+#: dashboards/project/containers/templates/containers/_create.html:22
+#: dashboards/project/containers/templates/containers/create.html:6
+msgid "Create Container"
+msgstr "Creare un Container"
+
+#: dashboards/project/containers/tables.py:69
+msgid "View Container"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:81
+#: dashboards/project/containers/templates/containers/_upload.html:23
+#: dashboards/project/containers/templates/containers/upload.html:3
+msgid "Upload Object"
+msgstr "Caricare un oggetto"
+
+#: dashboards/project/containers/tables.py:137
+#: dashboards/project/containers/tables.py:156
+msgid "Object"
+msgstr "Oggetto"
+
+#: dashboards/project/containers/tables.py:138
+#: dashboards/project/containers/tables.py:157
+#: dashboards/project/containers/tables.py:263
+msgid "Objects"
+msgstr "Oggetti"
+
+#: dashboards/project/containers/tables.py:149
+msgid "Folder"
+msgstr "Cartella"
+
+#: dashboards/project/containers/tables.py:150
+msgid "Folders"
+msgstr "Cartelle"
+
+#: dashboards/project/containers/tables.py:163
+msgid "Copy"
+msgstr "Copia"
+
+#: dashboards/project/containers/tables.py:176
+msgid "Download"
+msgstr "Scarica"
+
+#: dashboards/project/containers/tables.py:232
+msgid "Create Folder"
+msgstr "Crea cartella"
+
+#: dashboards/project/containers/views.py:53
+msgid "Unable to retrieve container list."
+msgstr "Impossibile recuperare la lista dei containers"
+
+#: dashboards/project/containers/views.py:82
+msgid "Unable to retrieve object list."
+msgstr "Impossible recuperare lista oggetti"
+
+#: dashboards/project/containers/views.py:166
+msgid "Unable to retrieve object."
+msgstr "Impossibile recuperare oggetto"
+
+#: dashboards/project/containers/views.py:200
+msgid "Unable to list containers."
+msgstr "Impossibile elencare i containers"
+
+#: dashboards/project/containers/templates/containers/_copy.html:7
+#: dashboards/project/containers/templates/containers/_copy.html:22
+#: dashboards/project/containers/templates/containers/copy.html:3
+#: dashboards/project/containers/templates/containers/copy.html:6
+msgid "Copy Object"
+msgstr "Copia oggetto"
+
+#: dashboards/project/containers/templates/containers/_copy.html:17
+msgid ""
+"Make a new copy of an existing object to store in this or another container. "
+"You may also specify a path at which the new copy should live inside of the "
+"selected container."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_create.html:17
+msgid ""
+"A container is a storage compartment for your data and provides a way for "
+"you to organize your data. You can think of a container as a folder in "
+"Windows &reg; or a directory in UNIX &reg;. The primary difference between a "
+"container and these other file system concepts is that containers cannot be "
+"nested. You can, however, create an unlimited number of containers within "
+"your account. Data must be stored in a container so you must have at least "
+"one container defined in your account prior to uploading data."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:8
+msgid "Upload Object To Container"
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:18
+msgid ""
+"An object is the basic storage entity and any optional metadata that "
+"represents the files you store in the OpenStack Object Storage system. When "
+"you upload data to OpenStack Object Storage, the data is stored as-is (no "
+"compression or encryption) and consists of a location (container), the "
+"object's name, and any metadata consisting of key/value pairs."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/upload.html:6
+msgid "Upload Objects"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/panel.py:26
+msgid "Images & Snapshots"
+msgstr "Immagini e Snapshots"
+
+#: dashboards/project/images_and_snapshots/views.py:63
+msgid "Unable to retrieve images."
+msgstr "Impossible recuperare immagini"
+
+#: dashboards/project/images_and_snapshots/views.py:74
+msgid "Unable to retrieve snapshots."
+msgstr "Impossibile recuperare le snapshots."
+
+#: dashboards/project/images_and_snapshots/views.py:82
+#: dashboards/project/volumes/forms.py:65
+msgid "Unable to retrieve volume snapshots."
+msgstr "Impossibile recuperare le snapshots del volume."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:42
+msgid "Image Location"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:43
+msgid "An external (HTTP) URL to load the image from."
+msgstr "Un URL esterno (HTTP) da cui caricare l'immagine."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:46
+#: dashboards/project/images_and_snapshots/images/forms.py:130
+#: dashboards/project/images_and_snapshots/images/tables.py:126
+msgid "Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:50
+msgid "AKI - Amazon Kernel Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:53
+msgid "AMI - Amazon Machine Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:56
+msgid "ARI - Amazon Ramdisk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:59
+msgid "ISO - Optical Disk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:61
+msgid "QCOW2 - QEMU Emulator"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:68
+msgid "Minimum Disk (GB)"
+msgstr "Minima dimensione disco (GB)"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:69
+#: dashboards/project/images_and_snapshots/images/forms.py:76
+msgid ""
+"The minimum disk size required to boot the image. If unspecified, this value "
+"defaults to 0 (no minimum)."
+msgstr ""
+"La dimensione minima del disco necessaria per avviare l'immagine. Se non "
+"specificata, questo valore sarà 0 (nessun minimo) per default"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:75
+msgid "Minimum Ram (MB)"
+msgstr "RAM minima (MB)"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:82
+#: dashboards/project/images_and_snapshots/images/forms.py:134
+#: dashboards/project/images_and_snapshots/images/tables.py:123
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:15
+msgid "Public"
+msgstr "Pubblica"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:106
+#, python-format
+msgid "Your image %s has been queued for creation."
+msgstr "La tua immagine %s è stata accodata per la creazione"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:110
+msgid "Unable to create new image."
+msgstr "Impossible creare una nuova immagine"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:116
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:48
+msgid "Kernel ID"
+msgstr "Kernel ID"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:121
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:52
+msgid "Ramdisk ID"
+msgstr "Ramdisk ID"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:126
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:44
+msgid "Architecture"
+msgstr "Architettura"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:138
+#, python-format
+msgid "Unable to update image \"%s\"."
+msgstr "Impossibile aggiornare immagine: \"%s\""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:162
+msgid "Image was successfully updated."
+msgstr "L'immagine è stata correttamente aggiornata."
+
+#: dashboards/project/images_and_snapshots/images/tables.py:34
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:33
+#: dashboards/project/instances/workflows.py:455
+msgid "Launch"
+msgstr "Avvia"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:46
+#: dashboards/project/images_and_snapshots/images/tables.py:82
+#: dashboards/project/instances/workflows.py:168
+#: dashboards/project/instances/workflows.py:173
+msgid "Image"
+msgstr "Immagine"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:61
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:31
+msgid "Create Image"
+msgstr "Crea immagine"
+
+#: dashboards/project/images_and_snapshots/images/tabs.py:38
+msgid "Unable to retrieve image details."
+msgstr "Impossible recuperare i dettagli dell'immagine"
+
+#: dashboards/project/images_and_snapshots/images/views.py:61
+msgid "Unable to retrieve image."
+msgstr "Impossibile recuperare immagine."
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:37
+msgid "Instance ID"
+msgstr "Instance ID"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:40
+#: dashboards/project/volumes/forms.py:193
+msgid "Snapshot Name"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:50
+#, python-format
+msgid "Snapshot \"%(name)s\" created for instance \"%(inst)s\""
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:56
+msgid "Unable to create snapshot."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:48
+#: dashboards/project/instances/workflows.py:107
+#: dashboards/project/instances/workflows.py:169
+msgid "Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:49
+msgid "Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:55
+msgid "Instance Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/views.py:53
+msgid "Unable to retrieve instance."
+msgstr "Impossibile recuperare istanza"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:6
+msgid "Images &amp; Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:6
+msgid "Create An Image"
+msgstr "Crea un'immagine"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:18
+msgid "Specify an image to upload to the Image Service."
+msgstr "Specifica un immagine da caricare su servizio Immagini"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:21
+msgid ""
+"Currently only images available via an HTTP URL are supported. The image "
+"location must be accessible to the Image Service. Compressed image binaries "
+"are supported (.zip and .tar.gz.)"
+msgstr ""
+"Al momento sono supportate esclusivamente immagini accessibili attraverso un "
+"indirizzo HTTP. L'indirizzo dell'immagine deve essere accessible dal "
+"servizio Immagini. Immagini compresse (.zip e .tar.gz) sono supportate."
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:24
+msgid "Please note: "
+msgstr "Per favore, osserva:"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:25
+#, fuzzy
+msgid ""
+"The Image Location field MUST be a valid and direct URL to the image binary. "
+"URLs that redirect or serve error pages will result in unusable images."
+msgstr ""
+"Il campo per l'indirizzo dell'immagine DEVE essere un URL valido e diretto "
+"per il file binario contenente l'immagine. L'utilizzo di URLs che effettuano "
+"un redirect o restituiscono pagine di errore comporterà l'inutilizzabilità "
+"dell'immagine."
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:3
+msgid "Image Overview"
+msgstr "Sommario Immagine"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:6
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:7
+#: dashboards/project/instances/templates/instances/_detail_overview.html:6
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:6
+msgid "Info"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:17
+msgid "Checksum"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:19
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:39
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:28
+msgid "Created"
+msgstr "Creata"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:21
+msgid "Updated"
+msgstr "Aggiornata"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:27
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:34
+#: dashboards/project/instances/templates/instances/_detail_overview.html:19
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:23
+msgid "Specs"
+msgstr "Specifiche"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:32
+msgid "Container Format"
+msgstr "Formato del container"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:34
+msgid "Disk Format"
+msgstr "Formato disco"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:40
+msgid "Custom Properties"
+msgstr "Proprietà personalizzate"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:56
+msgid "Euca2ools state"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:64
+msgid "Image Type"
+msgstr "Tipo immagine"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html:4
+msgid "Image Detail "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:8
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:3
+#: dashboards/project/instances/tables.py:179
+#: dashboards/project/volumes/tables.py:76
+msgid "Create Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:18
+msgid "Snapshots preserve the disk state of a running instance."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:20
+#: dashboards/project/instances/workflows.py:75
+#: dashboards/project/instances/workflows.py:110
+#: dashboards/project/instances/templates/instances/_detail_overview.html:93
+#: dashboards/project/volumes/tables.py:37
+#: dashboards/project/volumes/tables.py:182
+msgid "Volume"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:38
+#: dashboards/project/instances/templates/instances/_detail_overview.html:29
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:27
+msgid "GB"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:6
+msgid "Create a Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:3
+#, fuzzy
+msgid "Volume Snapshot Details"
+msgstr "Dettagli Volume"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:6
+#, fuzzy
+msgid "Volume Snapshot Detail"
+msgstr "Dettagli Volume"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:34
+#: dashboards/project/instances/workflows.py:76
+msgid "Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:35
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:85
+msgid "Volume Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:43
+#: dashboards/project/volumes/tables.py:59
+#: dashboards/project/volumes/templates/volumes/_create.html:8
+#: dashboards/project/volumes/templates/volumes/_create.html:55
+msgid "Create Volume"
+msgstr "Crea un volume"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:80
+#: dashboards/project/volumes/forms.py:26
+msgid "Volume Name"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:41
+#, fuzzy
+msgid "Unable to retrieve snapshot details."
+msgstr "Impossible recuperare informazioni sulle porte"
+
+#: dashboards/project/instances/forms.py:45
+#, python-format
+msgid "Instance \"%s\" updated."
+msgstr "Istanza \"%s\" aggiornata."
+
+#: dashboards/project/instances/forms.py:50
+msgid "Unable to update instance."
+msgstr "Impossibile aggiornare istanza."
+
+#: dashboards/project/instances/tables.py:67
+msgid "Terminate"
+msgstr "Termina"
+
+#: dashboards/project/instances/tables.py:68
+msgid "Scheduled termination of"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:87
+msgid "Reboot"
+msgstr "Riavvia"
+
+#: dashboards/project/instances/tables.py:88
+msgid "Rebooted"
+msgstr "Riavviata"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Pause"
+msgstr "Metti in pausa"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Unpause"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:105
+msgid "Paused"
+msgstr "Messa in pausa"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Unpaused"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:133
+msgid "Suspend"
+msgstr "Sospendi"
+
+#: dashboards/project/instances/tables.py:133
+msgid "Resume"
+msgstr "Riprendi"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Suspended"
+msgstr "Sospesa"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Resumed"
+msgstr "Ripresa"
+
+#: dashboards/project/instances/tables.py:162
+#: dashboards/project/instances/workflows.py:454
+#: dashboards/project/instances/templates/instances/launch.html:3
+#: dashboards/project/instances/templates/instances/launch.html:6
+msgid "Launch Instance"
+msgstr "Avvia istanza"
+
+#: dashboards/project/instances/tables.py:169
+#: dashboards/project/instances/templates/instances/_update.html:7
+msgid "Edit Instance"
+msgstr "Modifica istanza"
+
+#: dashboards/project/instances/tables.py:189
+msgid "VNC Console"
+msgstr "Console VNC"
+
+#: dashboards/project/instances/tables.py:204
+msgid "View Log"
+msgstr "Visualizza Log"
+
+#: dashboards/project/instances/tables.py:252
+#, python-format
+msgid "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disk"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:259
+#: dashboards/project/instances/tables.py:266
+msgid "Not available"
+msgstr "Non disponibile"
+
+#: dashboards/project/instances/tabs.py:36
+msgid "Log"
+msgstr "Log"
+
+#: dashboards/project/instances/tabs.py:48
+#: dashboards/project/instances/views.py:106
+#, python-format
+msgid "Unable to get log for instance \"%s\"."
+msgstr "Impossible recuperare log per istanza \"%s\""
+
+#: dashboards/project/instances/tabs.py:55
+msgid "VNC"
+msgstr "VNC"
+
+#: dashboards/project/instances/tabs.py:70
+#: dashboards/project/instances/views.py:122
+#, python-format
+msgid "Unable to get VNC console for instance \"%s\"."
+msgstr "Impossible recuperare la console VNC per l'istanza \"%s\""
+
+#: dashboards/project/instances/views.py:59
+msgid "Unable to retrieve instances."
+msgstr "Impossible recuperare istanze"
+
+#: dashboards/project/instances/views.py:144
+msgid "Unable to retrieve instance details."
+msgstr "Impossible recuperare dettagli istanza."
+
+#: dashboards/project/instances/views.py:179
+#, python-format
+msgid "Unable to retrieve details for instance \"%s\"."
+msgstr "Impossible recuperare i dettagli dell'istanza \"%s\""
+
+#: dashboards/project/instances/workflows.py:53
+msgid "Project & User"
+msgstr "Progetto ed Utente."
+
+#: dashboards/project/instances/workflows.py:66
+msgid "Don't boot from a volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:67
+msgid "Boot from volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:68
+msgid "Boot from volume snapshot (creates a new volume)."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:72
+#: dashboards/project/instances/workflows.py:90
+msgid "Volume Options"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:78
+#: dashboards/project/volumes/forms.py:126
+msgid "Device Name"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:81
+msgid "Volume mount point (e.g. 'vda' mounts at '/dev/vda')."
+msgstr "Punto di mount del volume (i.e. 'vda' mounts at '/dev/vda')"
+
+#: dashboards/project/instances/workflows.py:83
+msgid "Delete on Terminate"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:86
+msgid "Delete volume on instance terminate"
+msgstr "Elimina il volume quando l'istanza viene terminata"
+
+#: dashboards/project/instances/workflows.py:100
+#, python-format
+msgid "Please choose a volume, or select %s."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:117
+msgid "Select Volume"
+msgstr "Seleziona volume"
+
+#: dashboards/project/instances/workflows.py:125
+msgid "Unable to retrieve list of volumes."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:129
+msgid "Select Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:138
+msgid "Unable to retrieve list of volume snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:171
+msgid "Instance Source"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:174
+msgid "Instance Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:178
+msgid "Size of image to launch."
+msgstr "Dimensione dell'immagine da avviare"
+
+#: dashboards/project/instances/workflows.py:179
+msgid "Instance Count"
+msgstr "Totale istanze"
+
+#: dashboards/project/instances/workflows.py:182
+msgid "Number of instances to launch."
+msgstr "Numero di istanze da avviare"
+
+#: dashboards/project/instances/workflows.py:185
+msgid "Details"
+msgstr "Dettagli"
+
+#: dashboards/project/instances/workflows.py:198
+msgid ""
+"There are no image sources available; you must first create an image before "
+"attempting to launch an instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:203
+msgid "Please select an option for the instance source."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:212
+msgid ""
+"Launching multiple instances is only supported for images and instance "
+"snapshots."
+msgstr ""
+"L'avvio istanze multiple è supportato solo per immagini e 'snapshots' di "
+"istanze."
+
+#: dashboards/project/instances/workflows.py:229
+msgid "Unable to retrieve public images."
+msgstr "Impossible recuperare immagini pubbliche."
+
+#: dashboards/project/instances/workflows.py:244
+msgid "Unable to retrieve images for the current project."
+msgstr "Impossible recuperare immagini per il progetto corrente."
+
+#: dashboards/project/instances/workflows.py:267
+msgid "Select Image"
+msgstr "Seleziona un'immagine"
+
+#: dashboards/project/instances/workflows.py:269
+msgid "No images available."
+msgstr "Nessuna immagine disponibile"
+
+#: dashboards/project/instances/workflows.py:278
+msgid "Select Instance Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:280
+msgid "No snapshots available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:291
+msgid "Unable to retrieve instance flavors."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:304 usage/base.py:114
+msgid "Unable to retrieve quota information."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:337
+msgid "Which keypair to use for authentication."
+msgstr "Keypair da usare per l'autenticazione"
+
+#: dashboards/project/instances/workflows.py:344
+msgid "Launch instance in these security groups."
+msgstr "Avvia l'istanza con i seguenti 'security groups'"
+
+#: dashboards/project/instances/workflows.py:349
+msgid ""
+"Control access to your instance via keypairs, security groups, and other "
+"mechanisms."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:359
+msgid "Unable to retrieve keypairs."
+msgstr "Impossibile recuperare i keypairs"
+
+#: dashboards/project/instances/workflows.py:361
+msgid "Select a keypair"
+msgstr "Seleziona un keypair"
+
+#: dashboards/project/instances/workflows.py:363
+msgid "No keypairs available."
+msgstr "Nessun keypair disponibile"
+
+#: dashboards/project/instances/workflows.py:372
+msgid "Unable to retrieve list of security groups"
+msgstr "Impossibile recuperare la lista dei 'security groups'"
+
+#: dashboards/project/instances/workflows.py:392
+msgid "Customization Script"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:394
+msgid ""
+"A script or set of commands to be executed after the instance has been built "
+"(max 16kb)."
+msgstr ""
+"Uno script o un insieme di comandi da eseguire dopo che l'istanza e' stata "
+"assemblata (massimo 16kb)"
+
+#: dashboards/project/instances/workflows.py:401
+msgid "Post-Creation"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:415
+msgid "Launch instance withthese networks"
+msgstr "Avvia l'istanza con queste reti"
+
+#: dashboards/project/instances/workflows.py:419
+msgid "Networking"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:421
+msgid "Select networks for your instance."
+msgstr "Seleziona le reti per la tua istanza"
+
+#: dashboards/project/instances/workflows.py:433
+msgid "Unable to retrieve networks."
+msgstr "Impossibile recuperare reti"
+
+#: dashboards/project/instances/workflows.py:456
+#, python-format
+msgid "Launched %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:457
+#, python-format
+msgid "Unable to launch %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:470
+#, python-format
+msgid "%s instances"
+msgstr "%s istanze"
+
+#: dashboards/project/instances/workflows.py:473
+msgid "instance"
+msgstr "Istanza"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:4
+msgid "Instance Console Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:7
+msgid "Log Length"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:9
+msgid "Go"
+msgstr "Vai"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:11
+msgid "View Full Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:3
+msgid "Instance Overview"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:27
+msgid "VCPU"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:28
+#: usage/tables.py:20
+msgid "Disk"
+msgstr "Disco"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:34
+msgid "IP Addresses"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:59
+msgid "No rules defined."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:68
+msgid "Meta"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:71
+msgid "Key Name"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:84
+msgid "Volumes Attached"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:88
+#: dashboards/project/volumes/tables.py:167
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:38
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:45
+msgid "Attached To"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:90
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:42
+msgid "on"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:94
+msgid "No volumes attached."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:3
+msgid "Instance VNC Console"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid ""
+"If VNC console is not responding to keyboard input: click the grey status "
+"bar below."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid "Click here to show only VNC"
+msgstr "Cliccare qui per mostrare solo VNC"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:8
+msgid "VNC console is currently unavailabe. Please try again later."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:9
+msgid "Reload"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:2
+msgid ""
+"You can customize your instance after it's launched using the options "
+"available here."
+msgstr ""
+"E' possibile personalizzare l'istanza dopo l'avvio utilizzando le opzioni "
+"qui disponibili."
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:3
+msgid ""
+"The \"Customization Script\" field is analogous to \"User Data\" in other "
+"systems."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:3
+msgid "Specify the details for launching an instance."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:4
+msgid ""
+"The chart below shows the resources used by this project in relation to the "
+"project's quotas."
+msgstr ""
+"Il grafico sottostante mostra le risorse utilizzate da questo progetto in "
+"relazione alle quote stabilite per il progetto stesso."
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:6
+msgid "Flavor Details"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+msgid "Total Disk"
+msgstr "Totale disco"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "MB"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:21
+msgid "Number of Instances"
+msgstr "Numero istanze"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:29
+msgid "Number of VCPUs"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+#, fuzzy
+msgid "Total RAM"
+msgstr "Totale disco"
+
+#: dashboards/project/instances/templates/instances/_launch_volumes_help.html:3
+msgid ""
+"An instance can be launched with varying types of attached storage. You may "
+"select from those options here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_update.html:17
+msgid "You may update the editable properties of your instance here."
+msgstr "Le proprietà aggiornabili dell'istanza possono essere modificate qui."
+
+#: dashboards/project/instances/templates/instances/detail.html:3
+msgid "Instance Detail"
+msgstr "Dettagli istanza"
+
+#: dashboards/project/instances/templates/instances/update.html:3
+#: dashboards/project/instances/templates/instances/update.html:6
+msgid "Update Instance"
+msgstr ""
+
+#: dashboards/project/networks/tables.py:81
+msgid "Add Subnet"
+msgstr ""
+
+#: dashboards/project/networks/views.py:86
+msgid "Unable to retrieve network details."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:37
+msgid "Network Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:42
+msgid ""
+"From here you can create a new network.\n"
+"In addition a subnet associated with the network can be created in the next "
+"panel."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:56
+msgid "Subnet Name (optional)"
+msgstr "Nome della sottorete (opzionale)"
+
+#: dashboards/project/networks/workflows.py:61
+#: dashboards/project/networks/subnets/forms.py:48
+msgid "Network address in CIDR format (e.g. 192.168.0.0/24)"
+msgstr "Indirizzo di rete in formato CIDR (es: 192.168.0.0/24)"
+
+#: dashboards/project/networks/workflows.py:67
+msgid "Gateway IP (optional)"
+msgstr "Indirizzo IP del gateway (opzionale)"
+
+#: dashboards/project/networks/workflows.py:70
+#: dashboards/project/networks/subnets/forms.py:57
+#: dashboards/project/networks/subnets/forms.py:107
+msgid "IP address of Gateway (e.g. 192.168.0.1)"
+msgstr "Indirizzo IP del gateway (es: 192.168.0.1)"
+
+#: dashboards/project/networks/workflows.py:77
+msgid ""
+"You can create a subnet associated with the new network, in which case "
+"\"Network Address\" must be specified. If you wish to create a network "
+"WITHOUT a subnet, uncheck the \"Create Subnet\" checkbox."
+msgstr ""
+"Puoi creare una sottorete per la nuova rete; in tal caso e' necessario "
+"specificare l'indirizzo di rete. Se intendi creare una rete SENZA una "
+"sottorete, deseleziona la casella \"Crea Sottorete\"."
+
+#: dashboards/project/networks/workflows.py:89
+msgid "Specify \"Network Address\" or clear \"Create Subnet\" checkbox."
+msgstr ""
+"Specifica l'indirizzo di rete o deseleziona la casella \"Crea Sottorete\""
+
+#: dashboards/project/networks/workflows.py:94
+#: dashboards/project/networks/subnets/forms.py:70
+msgid "Network Address and IP version are inconsistent."
+msgstr ""
+"L'indirizzo di rete non è consistente con il versione del protocollo IP"
+
+#: dashboards/project/networks/workflows.py:98
+#: dashboards/project/networks/subnets/forms.py:74
+#: dashboards/project/networks/subnets/forms.py:119
+msgid "Gateway IP and IP version are inconsistent."
+msgstr ""
+"L'indirizzo del gateway non è consistente con la versione del protocollo IP"
+
+#: dashboards/project/networks/workflows.py:112
+msgid "Create"
+msgstr "Crea"
+
+#: dashboards/project/networks/workflows.py:113
+#, python-format
+msgid "Created network \"%s\"."
+msgstr "Rete \"%s\" creata."
+
+#: dashboards/project/networks/workflows.py:114
+#, python-format
+msgid "Unable to create network \"%s\"."
+msgstr "Impossibile create rete \"%s\"."
+
+#: dashboards/project/networks/workflows.py:130
+#, python-format
+msgid "Network \"%s\" was successfully created."
+msgstr "La rete \"%s\" è stata correttamente creata."
+
+#: dashboards/project/networks/workflows.py:133
+#, python-format
+msgid "Failed to create network \"%s\"."
+msgstr "Creazione della rete \"%s\" fallita."
+
+#: dashboards/project/networks/workflows.py:152
+#, python-format
+msgid "Subnet \"%s\" was successfully created."
+msgstr "La sottorete \"%s\" è stata correttamente creata."
+
+#: dashboards/project/networks/workflows.py:155
+#, python-format
+msgid "Failed to create subnet \"%(sub)s\" for network \"%(net)s\"."
+msgstr "Creazione della sottorete \"%(sub)s\" per la rete \"%(net)s\" fallita."
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Attached"
+msgstr "Allegato"
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Detached"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:85
+#, python-format
+msgid "Subnet %s was successfully created."
+msgstr "La sottorete %s é stata correttamente creata"
+
+#: dashboards/project/networks/subnets/forms.py:90
+#, python-format
+msgid "Failed to create subnet %s"
+msgstr "Creazione della sottorete %s fallita"
+
+#: dashboards/project/networks/subnets/forms.py:131
+#, python-format
+msgid "Subnet %s was successfully updated."
+msgstr "La sottorete %s é stata correttamente aggiornata"
+
+#: dashboards/project/networks/subnets/forms.py:136
+#, python-format
+msgid "Failed to update subnet %s"
+msgstr "Aggiornamento della sottorete %s fallito"
+
+#: dashboards/project/networks/subnets/tabs.py:42
+msgid "Unable to retrieve subnet details."
+msgstr "Impossible recuperare dettagli sottorete"
+
+#: dashboards/project/networks/templates/networks/_detail_overview.html:3
+msgid "Network Overview"
+msgstr "Riepilogo rete"
+
+#: dashboards/project/networks/templates/networks/detail.html:6
+msgid "Network Detail: "
+msgstr "Dettagli rete:"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:3
+msgid "Port Overview"
+msgstr "Riepilogo porta"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:17
+msgid "Fixed IP"
+msgstr "Indirizzo IP fisso"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:21
+msgid "IP address:"
+msgstr "Indirizzo Ip:"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:22
+msgid "Subnet ID"
+msgstr "ID sottorete"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:28
+msgid "Mac Address"
+msgstr "Indirizzo MAC"
+
+#: dashboards/project/networks/templates/networks/ports/detail.html:3
+#: dashboards/project/networks/templates/networks/ports/detail.html:6
+msgid "Port Detail"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:3
+msgid "Subnet Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:21
+msgid "IP allocation pool"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:24
+msgid "Start"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:25
+msgid " - End"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/detail.html:3
+#: dashboards/project/networks/templates/networks/subnets/detail.html:6
+msgid "Subnet Detail"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:29
+msgid "Size (GB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:30
+msgid "Use snapshot as a source"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:49
+#, python-format
+msgid "Volume size must be equal to or greater than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:54
+msgid "Unable to load the specified snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:59
+msgid "Choose a snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:83
+#, python-format
+msgid "The volume size cannot be less than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:92
+#, python-format
+msgid ""
+"A volume of %(req)iGB cannot be created as you only have %(avail)iGB of your "
+"quota available."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:99
+msgid "You are already using all of your available volumes."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:115
+msgid "Unable to create volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:123
+msgid "Attach to Instance"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:124
+msgid "Select an instance to attach to."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:168
+msgid "Unknown instance (None)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:179
+#, python-format
+msgid "Attaching volume %(vol)s to instance %(inst)s on %(dev)s."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:188
+msgid "Unable to attach volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:212
+#, python-format
+msgid "Creating volume snapshot \"%s\""
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:218
+msgid "Unable to create volume snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:46
+#, fuzzy, python-format
+msgid "Unable to delete volume \"%s\". One or more snapshots depend on it."
+msgstr "Impossibile recuperare le snapshots del volume."
+
+#: dashboards/project/volumes/tables.py:66
+msgid "Edit Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:93
+#, python-format
+msgid "%sGB"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:106
+#: dashboards/project/volumes/views.py:149
+msgid "Unable to retrieve attachment information."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:123
+#, python-format
+msgid "Attached to %(instance)s on %(dev)s"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:180
+msgid "Detach"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:181
+msgid "Detaching"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:216
+#, python-format
+msgid "%(dev)s on instance %(instance_name)s"
+msgstr ""
+
+#: dashboards/project/volumes/tabs.py:42
+msgid "Unable to retrieve volume details."
+msgstr "Impossible recuperare i dettagli del volume."
+
+#: dashboards/project/volumes/views.py:50
+msgid "Unable to retrieve volume list."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:58
+msgid "Unable to retrieve volume/instance attachment information"
+msgstr ""
+
+#: dashboards/project/volumes/views.py:130
+#: dashboards/project/volumes/views.py:140
+msgid "Unable to retrieve volume information."
+msgstr "Impossible recuperare informazioni sul volume."
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:9
+#: dashboards/project/volumes/templates/volumes/attach.html:6
+msgid "Manage Volume Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:13
+msgid "Attach To Instance"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:22
+msgid "Attach Volume"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:20
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:18
+msgid "Volumes are block devices that can be attached to instances."
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:22
+msgid "Volume Quotas"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:25
+msgid "Total Gigabytes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:34
+msgid "Number of Volumes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:8
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:23
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:3
+msgid "Create Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:3
+msgid "Volume Overview"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:34
+msgid "Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:46
+msgid "Not attached"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/create.html:6
+msgid "Create a Volume"
+msgstr "Crea un Volume"
+
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:6
+msgid "Create a Volume Snapshot"
+msgstr ""
+
+#: dashboards/settings/dashboard.py:24 templates/_header.html:4
+msgid "Settings"
+msgstr "Impostazioni"
+
+#: dashboards/settings/ec2/forms.py:36 dashboards/settings/project/forms.py:36
+msgid "Select a Project"
+msgstr "Seleziona Progetto"
+
+#: dashboards/settings/ec2/forms.py:46
+msgid "Unable to retrieve tenant list."
+msgstr "Impossible recuperare la lista dei 'tenants'"
+
+#: dashboards/settings/ec2/forms.py:88
+msgid "Unable to fetch EC2 credentials."
+msgstr "Impossible caricare le credenziali EC2"
+
+#: dashboards/settings/ec2/forms.py:101
+#, python-format
+msgid "Error writing zipfile: %(exc)s"
+msgstr "Errore nella creazione del file zip: %(exc)s"
+
+#: dashboards/settings/ec2/panel.py:25
+msgid "EC2 Credentials"
+msgstr "Credenziali EC2"
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:8
+#: dashboards/settings/ec2/templates/ec2/download_form.html:23
+#: dashboards/settings/ec2/templates/ec2/index.html:3
+#: dashboards/settings/ec2/templates/ec2/index.html:6
+msgid "Download EC2 Credentials"
+msgstr "Scarica credenziali EC2"
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:18
+msgid ""
+"Clicking \"Download EC2 Credentials\" will download a zip file which "
+"includes an rc file with your access/secret keys, as well as your x509 "
+"private key and certificate."
+msgstr ""
+"Cliccando \"Scarica credenziali EC2\" verrà scaricato un file ZIP che "
+"include un file RC contenente la chiave d'accesso e la chiave segreta, "
+"nonchè il certificato x509 e la chiave privata."
+
+#: dashboards/settings/project/forms.py:71
+#, python-format
+msgid "Error Downloading RC File: %s"
+msgstr "Errore nel download del file RC: %s"
+
+#: dashboards/settings/project/panel.py:25
+#: dashboards/settings/project/templates/project/_openrc.html:8
+#: dashboards/settings/project/templates/project/settings.html:3
+#: dashboards/settings/project/templates/project/settings.html:6
+msgid "OpenStack API"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:27
+msgid "Service Name"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:29
+msgid "Service Endpoint"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:33
+msgid "API Endpoints"
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:15
+msgid "Download OpenStack RC File"
+msgstr "Scarica file RC per Openstack"
+
+#: dashboards/settings/project/templates/project/_openrc.html:25
+msgid ""
+"Download the RC file for the selected project, then type \"source openrc\" "
+"in the terminal to configure your environment to communicate with OpenStack."
+msgstr ""
+"Scarica il file RC per il progetto selezionato. Quindi digita \"source openrc"
+"\" al terminale per configurare il tuo ambiente per comunicare con Openstack."
+
+#: dashboards/settings/project/templates/project/_openrc.html:30
+msgid "Download RC File"
+msgstr "Scarica file RC"
+
+#: dashboards/settings/user/forms.py:57
+msgid "Settings saved."
+msgstr ""
+
+#: dashboards/settings/user/panel.py:25
+#: dashboards/settings/user/templates/user/_settings.html:8
+#: dashboards/settings/user/templates/user/settings.html:3
+#: dashboards/settings/user/templates/user/settings.html:6
+msgid "User Settings"
+msgstr "Impostazioni utente"
+
+#: dashboards/settings/user/templates/user/_settings.html:18
+msgid "From here you can modify dashboard settings for your user."
+msgstr ""
+"Da qui puoi modificare le impostazioni del cruscotto per il tuo utente."
+
+#: templates/403.html:4 templates/403.html.py:9
+msgid "Forbidden"
+msgstr ""
+
+#: templates/403.html:20 templates/404.html:19 templates/500.html:19
+msgid "Home"
+msgstr ""
+
+#: templates/404.html:4
+msgid "Page Not Found"
+msgstr ""
+
+#: templates/404.html:9
+msgid "The page you were looking for doesn't exist"
+msgstr ""
+
+#: templates/404.html:10
+msgid "You may have mistyped the address or the page may have moved."
+msgstr ""
+
+#: templates/500.html:4 templates/500.html.py:9
+msgid "Internal Server Error"
+msgstr ""
+
+#: templates/500.html:10
+msgid ""
+"An unexpected error occurred while processing your request. Please try your "
+"request again."
+msgstr ""
+
+#: templates/_header.html:3
+msgid "Logged in as"
+msgstr ""
+
+#: templates/_header.html:6
+msgid "Help"
+msgstr ""
+
+#: templates/_header.html:8
+msgid "Sign Out"
+msgstr ""
+
+#: test/settings.py:50
+msgid "Password must be between 8 and 18 characters."
+msgstr ""
+
+#: usage/base.py:97
+msgid "Unable to retrieve usage information."
+msgstr "Impossible recuperate informazioni di utilizzo."
+
+#: usage/base.py:100
+msgid "You are viewing data for the future, which may or may not exist."
+msgstr ""
+"Stai vedendo dati relativi al futuro, che potrebbero o non potrebbero "
+"esistere."
+
+#: usage/tables.py:11
+msgid "Download CSV Summary"
+msgstr "Scarica riepilogo in formato CSV."
+
+#: usage/tables.py:25
+msgid "VCPU Hours"
+msgstr ""
+
+#: usage/tables.py:32
+msgid "Disk GB Hours"
+msgstr ""
+
+#: usage/tables.py:40 usage/tables.py:68
+msgid "Usage Summary"
+msgstr "Riepilogo utilizzo."
+
+#: usage/tables.py:60
+msgid "Uptime"
+msgstr ""
diff --git a/openstack_dashboard/locale/ja/LC_MESSAGES/django.mo b/openstack_dashboard/locale/ja/LC_MESSAGES/django.mo
index 15801804c..359a00b39 100644
--- a/openstack_dashboard/locale/ja/LC_MESSAGES/django.mo
+++ b/openstack_dashboard/locale/ja/LC_MESSAGES/django.mo
Binary files differ
diff --git a/openstack_dashboard/locale/ja/LC_MESSAGES/django.po b/openstack_dashboard/locale/ja/LC_MESSAGES/django.po
index d7abd6cd2..3fea50f92 100644
--- a/openstack_dashboard/locale/ja/LC_MESSAGES/django.po
+++ b/openstack_dashboard/locale/ja/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Horizon\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-09-18 22:18+0000\n"
+"POT-Creation-Date: 2012-10-05 19:30+0000\n"
"PO-Revision-Date: 2012-08-24 05:18+0000\n"
"Last-Translator: Tomoyuki KATO <tomo@dream.daynight.jp>\n"
"Language-Team: Japanese (http://www.transifex.com/projects/p/openstack/"
@@ -19,63 +19,3308 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-#: settings.py:141
+#: settings.py:142
msgid "Bulgarian (Bulgaria)"
msgstr ""
-#: settings.py:142
+#: settings.py:143
msgid "Czech"
msgstr ""
-#: settings.py:143
+#: settings.py:144
msgid "English"
msgstr "英語"
-#: settings.py:144
+#: settings.py:145
msgid "Spanish"
msgstr "スペイン語"
-#: settings.py:145
+#: settings.py:146
msgid "French"
msgstr "フランス語"
-#: settings.py:146
+#: settings.py:147
msgid "Italiano"
msgstr "イタリア語"
-#: settings.py:147
+#: settings.py:148
msgid "Japanese"
msgstr "日本語"
-#: settings.py:148
+#: settings.py:149
msgid "Korean (Korea)"
msgstr ""
-#: settings.py:149
+#: settings.py:150
msgid "Dutch (Netherlands)"
msgstr ""
-#: settings.py:150
+#: settings.py:151
msgid "Polish"
msgstr "ポーランド語"
-#: settings.py:151
+#: settings.py:152
msgid "Portuguese"
msgstr "ポルトガル語"
-#: settings.py:152
+#: settings.py:153
#, fuzzy
msgid "Portuguese (Brazil)"
msgstr "ポルトガル語"
-#: settings.py:153
+#: settings.py:154
msgid "Simplified Chinese"
msgstr "簡体字中国語"
-#: settings.py:154
+#: settings.py:155
msgid "Traditional Chinese"
msgstr "繁体字中国語"
+#: api/keystone.py:56
+#, python-format
+msgid "%(type)s (%(backend)s backend)"
+msgstr "%(type)s (%(backend)s バックエンド)"
+
+#: api/nova.py:191
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(group)s"
+msgstr "%(group)s からポート番号 %(from)s:%(to)s への通信を許可"
+
+#: api/nova.py:196
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(cidr)s"
+msgstr "%(cidr)s からポート番号 %(from)s:%(to)s への通信を許可"
+
+#: api/nova.py:532
+msgid "Unknown instance"
+msgstr "未知のインスタンス"
+
+#: api/swift.py:217
+msgid "Unicode is not currently supported for object copy."
+msgstr "オブジェクトのコピーで Unicode は現在サポートされていません。"
+
+#: dashboards/admin/dashboard.py:24
+msgid "System Panel"
+msgstr "システムパネル"
+
+#: dashboards/admin/dashboard.py:30
+msgid "Admin"
+msgstr "管理"
+
+#: dashboards/admin/flavors/forms.py:36 dashboards/admin/networks/forms.py:34
+#: dashboards/admin/networks/forms.py:69
+#: dashboards/admin/networks/ports/forms.py:40
+#: dashboards/admin/networks/ports/forms.py:72
+#: dashboards/admin/networks/ports/tables.py:73
+#: dashboards/admin/networks/subnets/tables.py:70
+#: dashboards/admin/projects/tables.py:87
+#: dashboards/admin/projects/workflows.py:71
+#: dashboards/admin/services/tables.py:38
+#: dashboards/admin/volumes/tables.py:10
+#: dashboards/project/access_and_security/security_groups/forms.py:36
+#: dashboards/project/access_and_security/security_groups/tables.py:58
+#: dashboards/project/images_and_snapshots/images/forms.py:40
+#: dashboards/project/images_and_snapshots/images/forms.py:115
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:9
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:10
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:77
+#: dashboards/project/instances/templates/instances/_detail_overview.html:9
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:9
+#: dashboards/project/networks/forms.py:37
+#: dashboards/project/networks/tables.py:94
+#: dashboards/project/networks/ports/tables.py:40
+#: dashboards/project/networks/subnets/forms.py:43
+#: dashboards/project/networks/subnets/forms.py:102
+#: dashboards/project/networks/subnets/tables.py:82
+#: dashboards/project/networks/templates/networks/_detail_overview.html:7
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:9
+#: dashboards/project/volumes/tables.py:144
+#: dashboards/project/volumes/tables.py:164
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:9
+msgid "Name"
+msgstr "名前"
+
+#: dashboards/admin/flavors/forms.py:37 dashboards/admin/flavors/tables.py:41
+#: dashboards/admin/projects/workflows.py:39
+#: dashboards/project/instances/templates/instances/_detail_overview.html:26
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:10
+#: usage/tables.py:19
+msgid "VCPUs"
+msgstr "仮想 CPU"
+
+#: dashboards/admin/flavors/forms.py:38
+#, fuzzy
+msgid "RAM MB"
+msgstr "メモリー (MB)"
+
+#: dashboards/admin/flavors/forms.py:39
+msgid "Root Disk GB"
+msgstr "ルートディスク GB"
+
+#: dashboards/admin/flavors/forms.py:40
+msgid "Ephemeral Disk GB"
+msgstr "一時ディスク GB"
+
+#: dashboards/admin/flavors/forms.py:50
+msgid "Unable to get unique ID for new flavor."
+msgstr "新しいインタスタンスタイプの一意な ID を取得できません。"
+
+#: dashboards/admin/flavors/forms.py:67
+#, python-format
+msgid "Created flavor \"%s\"."
+msgstr "インタスタンスタイプ \"%s\" を作成しました。"
+
+#: dashboards/admin/flavors/forms.py:71
+msgid "Unable to create flavor."
+msgstr "インタスタンスタイプを作成できません。"
+
+#: dashboards/admin/flavors/forms.py:92
+#, python-format
+msgid "Updated flavor \"%s\"."
+msgstr "インタスタンスタイプ \"%s\" を更新しました。"
+
+#: dashboards/admin/flavors/forms.py:96
+msgid "Unable to update flavor."
+msgstr "インタスタンスタイプを更新できません。"
+
+#: dashboards/admin/flavors/panel.py:29 dashboards/admin/flavors/tables.py:15
+#: dashboards/admin/flavors/tables.py:52
+#: dashboards/admin/flavors/templates/flavors/index.html:3
+#: dashboards/admin/flavors/templates/flavors/index.html:6
+msgid "Flavors"
+msgstr "インタスタンスタイプ"
+
+#: dashboards/admin/flavors/tables.py:14
+#: dashboards/project/instances/workflows.py:177
+#: dashboards/project/instances/templates/instances/_detail_overview.html:22
+msgid "Flavor"
+msgstr "インタスタンスタイプ"
+
+#: dashboards/admin/flavors/tables.py:23
+#: dashboards/admin/flavors/templates/flavors/_create.html:8
+#: dashboards/admin/flavors/templates/flavors/_create.html:23
+#: dashboards/admin/flavors/templates/flavors/create.html:3
+#: dashboards/admin/flavors/templates/flavors/create.html:6
+msgid "Create Flavor"
+msgstr "インタスタンスタイプの作成"
+
+#: dashboards/admin/flavors/tables.py:30
+#: dashboards/admin/flavors/templates/flavors/_edit.html:8
+#: dashboards/admin/flavors/templates/flavors/edit.html:3
+#: dashboards/admin/flavors/templates/flavors/edit.html:6
+msgid "Edit Flavor"
+msgstr "インタスタンスタイプの編集"
+
+#: dashboards/admin/flavors/tables.py:36
+#, python-format
+msgid "%sMB"
+msgstr "%sMB"
+
+#: dashboards/admin/flavors/tables.py:40
+msgid "Flavor Name"
+msgstr "インタスタンスタイプ名"
+
+#: dashboards/admin/flavors/tables.py:43
+#: dashboards/project/instances/templates/instances/_detail_overview.html:24
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: usage/tables.py:22
+msgid "RAM"
+msgstr "RAM"
+
+#: dashboards/admin/flavors/tables.py:45
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+msgid "Root Disk"
+msgstr "ルートディスク"
+
+#: dashboards/admin/flavors/tables.py:47
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+msgid "Ephemeral Disk"
+msgstr "一時ディスク"
+
+#: dashboards/admin/flavors/views.py:49
+msgid "Unable to retrieve flavor list."
+msgstr "インタスタンスタイプ一覧を取得できません。"
+
+#: dashboards/admin/flavors/views.py:76
+msgid "Unable to retrieve flavor data."
+msgstr "インタスタンスタイプのデータを取得できません。"
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:17
+#: dashboards/admin/flavors/templates/flavors/_edit.html:17
+#: dashboards/admin/images/templates/images/_update.html:17
+#: dashboards/admin/networks/templates/networks/_create.html:17
+#: dashboards/admin/networks/templates/networks/ports/_create.html:17
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:17
+#: dashboards/admin/projects/tables.py:89
+#: dashboards/admin/projects/workflows.py:74
+#: dashboards/admin/projects/templates/projects/_add_user.html:17
+#: dashboards/admin/projects/templates/projects/_create.html:17
+#: dashboards/admin/projects/templates/projects/_create_user.html:17
+#: dashboards/admin/projects/templates/projects/_quotas.html:16
+#: dashboards/admin/projects/templates/projects/_update.html:17
+#: dashboards/admin/users/templates/users/_create.html:16
+#: dashboards/admin/users/templates/users/_update.html:16
+#: dashboards/project/access_and_security/security_groups/forms.py:38
+#: dashboards/project/access_and_security/security_groups/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:17
+#: dashboards/project/containers/templates/containers/_copy.html:16
+#: dashboards/project/containers/templates/containers/_create.html:16
+#: dashboards/project/containers/templates/containers/_upload.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/_create.html:16
+#: dashboards/project/networks/templates/networks/subnets/_create.html:17
+#: dashboards/project/volumes/forms.py:28
+#: dashboards/project/volumes/forms.py:195
+#: dashboards/project/volumes/tables.py:147
+#: dashboards/project/volumes/templates/volumes/_create.html:18
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:17
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:14
+msgid "Description"
+msgstr "説明"
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:18
+msgid "From here you can define the sizing of a new flavor."
+msgstr "ここから新しいインタスタンスタイプの大きさを定義できます。"
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:24
+#: dashboards/admin/flavors/templates/flavors/_edit.html:25
+#: dashboards/admin/images/templates/images/_update.html:24
+#: dashboards/admin/networks/templates/networks/_create.html:24
+#: dashboards/admin/networks/templates/networks/_update.html:23
+#: dashboards/admin/networks/templates/networks/ports/_create.html:24
+#: dashboards/admin/networks/templates/networks/ports/_update.html:28
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:24
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:32
+#: dashboards/admin/projects/templates/projects/_add_user.html:24
+#: dashboards/admin/projects/templates/projects/_create.html:24
+#: dashboards/admin/projects/templates/projects/_create_user.html:24
+#: dashboards/admin/projects/templates/projects/_quotas.html:23
+#: dashboards/admin/projects/templates/projects/_update.html:24
+#: dashboards/admin/users/templates/users/_create.html:23
+#: dashboards/admin/users/templates/users/_update.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:32
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:20
+#: dashboards/project/containers/templates/containers/_copy.html:23
+#: dashboards/project/containers/templates/containers/_create.html:23
+#: dashboards/project/containers/templates/containers/_upload.html:24
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:32
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:24
+#: dashboards/project/instances/templates/instances/_update.html:23
+#: dashboards/project/networks/templates/networks/_create.html:23
+#: dashboards/project/networks/templates/networks/_update.html:23
+#: dashboards/project/networks/templates/networks/subnets/_create.html:24
+#: dashboards/project/networks/templates/networks/subnets/_update.html:32
+#: dashboards/project/volumes/templates/volumes/_attach.html:24
+#: dashboards/project/volumes/templates/volumes/_create.html:56
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:24
+#: dashboards/settings/ec2/templates/ec2/download_form.html:24
+#: dashboards/settings/project/templates/project/_openrc.html:31
+#: dashboards/settings/user/templates/user/_settings.html:24
+msgid "Cancel"
+msgstr "キャンセル"
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:18
+msgid "From here you can alter the sizing of the current flavor."
+msgstr "現在のインスタンスタイプのサイズを変更できます。"
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:19
+msgid ""
+"Note: this will not affect the resources allocated to any existing instances "
+"using this flavor."
+msgstr ""
+"注: このインスタンスタイプを使用している既存のインスタンスに割り当てられたリ"
+"ソースには影響しません。"
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:24
+#: dashboards/admin/projects/workflows.py:270
+#: dashboards/settings/user/templates/user/_settings.html:23
+msgid "Save"
+msgstr "保存"
+
+#: dashboards/admin/images/panel.py:29 dashboards/admin/images/tables.py:44
+#: dashboards/admin/images/templates/images/index.html:3
+#: dashboards/admin/images/templates/images/index.html:6
+#: dashboards/project/images_and_snapshots/images/tables.py:47
+#: dashboards/project/images_and_snapshots/images/tables.py:132
+msgid "Images"
+msgstr "イメージ"
+
+#: dashboards/admin/images/tables.py:40
+#: dashboards/project/images_and_snapshots/images/tables.py:113
+#: dashboards/project/instances/templates/instances/_detail_overview.html:74
+msgid "Image Name"
+msgstr "イメージ名"
+
+#: dashboards/admin/images/views.py:55
+msgid "Unable to retrieve image list."
+msgstr "イメージの一覧を取り出せません。"
+
+#: dashboards/admin/images/templates/images/_update.html:8
+#: dashboards/admin/images/templates/images/_update.html:23
+#: dashboards/admin/images/templates/images/update.html:4
+#: dashboards/admin/images/templates/images/update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:22
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:6
+msgid "Update Image"
+msgstr "イメージの更新"
+
+#: dashboards/admin/images/templates/images/_update.html:18
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:17
+msgid "From here you can modify different properties of an image."
+msgstr "イメージのプロパティーを変更します。"
+
+#: dashboards/admin/instances/panel.py:29
+#: dashboards/admin/instances/tables.py:94
+#: dashboards/admin/instances/templates/instances/index.html:3
+#: dashboards/admin/projects/workflows.py:40
+#: dashboards/project/instances/panel.py:25
+#: dashboards/project/instances/tables.py:70
+#: dashboards/project/instances/tables.py:90
+#: dashboards/project/instances/tables.py:107
+#: dashboards/project/instances/tables.py:136
+#: dashboards/project/instances/tables.py:313
+#: dashboards/project/instances/templates/instances/index.html:3
+#: dashboards/project/instances/templates/instances/index.html:6
+msgid "Instances"
+msgstr "インスタンス"
+
+#: dashboards/admin/instances/tables.py:60 usage/tables.py:30
+msgid "Project Name"
+msgstr "プロジェクト名"
+
+#: dashboards/admin/instances/tables.py:67
+#: dashboards/admin/services/tables.py:40
+msgid "Host"
+msgstr "ホスト"
+
+#: dashboards/admin/instances/tables.py:71
+#: dashboards/project/instances/tables.py:290
+#: dashboards/project/instances/workflows.py:176 usage/tables.py:57
+msgid "Instance Name"
+msgstr "インスタンス名"
+
+#: dashboards/admin/instances/tables.py:72
+#: dashboards/project/access_and_security/floating_ips/tables.py:111
+#: dashboards/project/access_and_security/floating_ips/workflows.py:32
+#: dashboards/project/access_and_security/floating_ips/workflows.py:39
+#: dashboards/project/instances/tables.py:291
+msgid "IP Address"
+msgstr "IP アドレス"
+
+#: dashboards/admin/instances/tables.py:74
+#: dashboards/project/containers/tables.py:256
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:30
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:37
+#: dashboards/project/instances/tables.py:293
+#: dashboards/project/volumes/tables.py:150
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:26
+msgid "Size"
+msgstr "サイズ"
+
+#: dashboards/admin/instances/tables.py:79
+#: dashboards/admin/networks/tables.py:74
+#: dashboards/admin/networks/ports/tables.py:77
+#: dashboards/project/images_and_snapshots/images/tables.py:119
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:13
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:18
+#: dashboards/project/instances/tables.py:298
+#: dashboards/project/instances/templates/instances/_detail_overview.html:13
+#: dashboards/project/networks/tables.py:100
+#: dashboards/project/networks/ports/tables.py:44
+#: dashboards/project/networks/templates/networks/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:30
+#: dashboards/project/volumes/tables.py:154
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:17
+msgid "Status"
+msgstr "ステータス"
+
+#: dashboards/admin/instances/tables.py:83
+#: dashboards/project/instances/tables.py:302
+msgid "Task"
+msgstr "タスク"
+
+#: dashboards/admin/instances/tables.py:90
+#: dashboards/project/instances/tables.py:309
+msgid "Power State"
+msgstr "稼働状態"
+
+#: dashboards/admin/instances/views.py:49
+#: dashboards/project/access_and_security/views.py:76
+#: dashboards/project/access_and_security/floating_ips/workflows.py:65
+msgid "Unable to retrieve instance list."
+msgstr "インスタンスの一覧を取得できません。"
+
+#: dashboards/admin/instances/views.py:63
+#: dashboards/admin/networks/views.py:48
+msgid "Unable to retrieve instance tenant information."
+msgstr "インスタンスのプロジェクト情報を取得できません。"
+
+#: dashboards/admin/instances/views.py:80
+#: dashboards/project/instances/views.py:82
+msgid "Unable to retrieve instance size information."
+msgstr "インスタンスの容量情報を取得できません。"
+
+#: dashboards/admin/instances/templates/instances/index.html:6
+msgid "All Instances"
+msgstr "すべてのインスタンス"
+
+#: dashboards/admin/networks/forms.py:36
+#: dashboards/admin/networks/tables.py:67
+#: dashboards/admin/projects/tables.py:65 dashboards/project/dashboard.py:40
+#: dashboards/project/instances/workflows.py:38
+msgid "Project"
+msgstr "プロジェクト"
+
+#: dashboards/admin/networks/forms.py:37 dashboards/admin/networks/forms.py:74
+#: dashboards/admin/networks/tables.py:72
+#: dashboards/project/networks/tables.py:98
+#: dashboards/project/networks/templates/networks/_detail_overview.html:17
+msgid "Shared"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:46 dashboards/admin/users/forms.py:42
+msgid "Select a project"
+msgstr "プロジェクトの選択"
+
+#: dashboards/admin/networks/forms.py:58
+#, python-format
+msgid "Network %s was successfully created."
+msgstr "ネットワーク %s が正常に作成されました。"
+
+#: dashboards/admin/networks/forms.py:64
+#, python-format
+msgid "Failed to create network %s"
+msgstr "ネットワーク %s の作成に失敗しました"
+
+#: dashboards/admin/networks/forms.py:71
+#: dashboards/admin/networks/templates/networks/ports/_update.html:12
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:12
+#: dashboards/admin/users/forms.py:114
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:11
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:12
+#: dashboards/project/instances/templates/instances/_detail_overview.html:11
+#: dashboards/project/networks/forms.py:39
+#: dashboards/project/networks/templates/networks/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_update.html:12
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:11
+msgid "ID"
+msgstr "ID"
+
+#: dashboards/admin/networks/forms.py:82
+#: dashboards/project/networks/forms.py:48
+#, python-format
+msgid "Network %s was successfully updated."
+msgstr "ネットワーク %s が正常に更新されました。"
+
+#: dashboards/admin/networks/forms.py:87
+#: dashboards/project/networks/forms.py:53
+#, python-format
+msgid "Failed to update network %s"
+msgstr "ネットワーク %s の更新に失敗しました"
+
+#: dashboards/admin/networks/panel.py:25
+#: dashboards/admin/networks/tables.py:35
+#: dashboards/admin/networks/tables.py:80
+#: dashboards/admin/networks/templates/networks/index.html:3
+#: dashboards/admin/networks/templates/networks/index.html:6
+#: dashboards/project/instances/workflows.py:412
+#: dashboards/project/networks/panel.py:25
+#: dashboards/project/networks/tables.py:44
+#: dashboards/project/networks/tables.py:106
+#: dashboards/project/networks/templates/networks/index.html:3
+#: dashboards/project/networks/templates/networks/index.html:6
+msgid "Networks"
+msgstr "ネットワーク"
+
+#: dashboards/admin/networks/tables.py:34
+#: dashboards/project/networks/tables.py:43
+#: dashboards/project/networks/templates/networks/subnets/index.html:3
+#: dashboards/project/networks/templates/networks/subnets/index.html:6
+msgid "Network"
+msgstr "ネットワーク"
+
+#: dashboards/admin/networks/tables.py:41
+#: dashboards/project/networks/tables.py:59
+#, python-format
+msgid "Failed to delete network %s"
+msgstr "ネットワーク %s の削除に失敗しました"
+
+#: dashboards/admin/networks/tables.py:49
+#: dashboards/admin/networks/templates/networks/_create.html:8
+#: dashboards/admin/networks/templates/networks/_create.html:23
+#: dashboards/admin/networks/templates/networks/create.html:3
+#: dashboards/admin/networks/templates/networks/create.html:6
+#: dashboards/project/networks/tables.py:67
+#: dashboards/project/networks/workflows.py:111
+#: dashboards/project/networks/templates/networks/_create.html:7
+#: dashboards/project/networks/templates/networks/_create.html:22
+#: dashboards/project/networks/templates/networks/create.html:3
+#: dashboards/project/networks/templates/networks/create.html:6
+msgid "Create Network"
+msgstr "ネットワークの作成"
+
+#: dashboards/admin/networks/tables.py:56
+#: dashboards/admin/networks/templates/networks/_update.html:7
+#: dashboards/project/networks/tables.py:74
+#: dashboards/project/networks/templates/networks/_update.html:7
+msgid "Edit Network"
+msgstr "ネットワークの編集"
+
+#: dashboards/admin/networks/tables.py:68
+#: dashboards/admin/networks/ports/forms.py:33
+#: dashboards/project/networks/subnets/forms.py:35
+msgid "Network Name"
+msgstr "ネットワーク名"
+
+#: dashboards/admin/networks/tables.py:71
+#: dashboards/project/networks/tables.py:97
+msgid "Subnets Associated"
+msgstr "関連サブネット"
+
+#: dashboards/admin/networks/tables.py:76
+#: dashboards/admin/networks/ports/tables.py:79
+#: dashboards/project/networks/tables.py:102
+#: dashboards/project/networks/ports/tables.py:46
+#: dashboards/project/networks/templates/networks/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:32
+msgid "Admin State"
+msgstr "管理者状態"
+
+#: dashboards/admin/networks/views.py:60
+#: dashboards/project/networks/views.py:52
+msgid "Network list can not be retrieved."
+msgstr "ネットワーク一覧を取得できません。"
+
+#: dashboards/admin/networks/views.py:91
+#: dashboards/project/networks/views.py:109
+msgid "Subnet list can not be retrieved."
+msgstr "サブネット一覧を取得できません。"
+
+#: dashboards/admin/networks/views.py:103
+#: dashboards/project/networks/views.py:121
+msgid "Port list can not be retrieved."
+msgstr "ポート一覧を取得できません。"
+
+#: dashboards/admin/networks/views.py:118
+#: dashboards/project/networks/views.py:134
+#: dashboards/project/networks/subnets/tables.py:96
+#, python-format
+msgid "Unable to retrieve details for network \"%s\"."
+msgstr "ネットワーク \"%s\" の詳細を取得できません。"
+
+#: dashboards/admin/networks/ports/forms.py:36
+#: dashboards/project/networks/subnets/forms.py:39
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:13
+msgid "Network ID"
+msgstr "ネットワーク ID"
+
+#: dashboards/admin/networks/ports/forms.py:42
+#: dashboards/admin/networks/ports/forms.py:74
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:34
+msgid "Device ID"
+msgstr "デバイス ID"
+
+#: dashboards/admin/networks/ports/forms.py:54
+#, python-format
+msgid "Port %s was successfully created."
+msgstr "ポート %s が正常に作成されました。"
+
+#: dashboards/admin/networks/ports/forms.py:59
+#, python-format
+msgid "Failed to create a port for network %s"
+msgstr "ネットワーク %s のポートの作成に失敗しました"
+
+#: dashboards/admin/networks/ports/forms.py:84
+#, python-format
+msgid "Port %s was successfully updated."
+msgstr "ポート %s が正常に更新されました。"
+
+#: dashboards/admin/networks/ports/forms.py:89
+#, python-format
+msgid "Failed to update port %s"
+msgstr "ポート %s の更新に失敗しました"
+
+#: dashboards/admin/networks/ports/tables.py:34
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:6
+msgid "Port"
+msgstr "ポート"
+
+#: dashboards/admin/networks/ports/tables.py:35
+#: dashboards/admin/networks/ports/tables.py:83
+#: dashboards/project/networks/ports/tables.py:53
+msgid "Ports"
+msgstr "ポート"
+
+#: dashboards/admin/networks/ports/tables.py:41
+#: dashboards/admin/networks/subnets/tables.py:39
+#: dashboards/project/networks/subnets/tables.py:51
+#, python-format
+msgid "Failed to delete subnet %s"
+msgstr "サブネット %s の削除に失敗しました"
+
+#: dashboards/admin/networks/ports/tables.py:51
+#: dashboards/admin/networks/templates/networks/ports/_create.html:8
+#: dashboards/admin/networks/templates/networks/ports/_create.html:23
+#: dashboards/admin/networks/templates/networks/ports/create.html:3
+#: dashboards/admin/networks/templates/networks/ports/create.html:6
+msgid "Create Port"
+msgstr "ポートの作成"
+
+#: dashboards/admin/networks/ports/tables.py:62
+#: dashboards/admin/networks/templates/networks/ports/_update.html:7
+msgid "Edit Port"
+msgstr "ポートの編集"
+
+#: dashboards/admin/networks/ports/tables.py:75
+#: dashboards/project/networks/ports/tables.py:42
+msgid "Fixed IPs"
+msgstr "固定 IP"
+
+#: dashboards/admin/networks/ports/tables.py:76
+#: dashboards/project/networks/ports/tables.py:43
+msgid "Device Attached"
+msgstr "デバイスを接続しました"
+
+#: dashboards/admin/networks/ports/tabs.py:32
+#: dashboards/admin/overview/panel.py:29
+#: dashboards/admin/overview/templates/overview/usage.html:6
+#: dashboards/project/images_and_snapshots/images/tabs.py:27
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:27
+#: dashboards/project/instances/tabs.py:26
+#: dashboards/project/networks/ports/tabs.py:32
+#: dashboards/project/networks/subnets/tabs.py:32
+#: dashboards/project/overview/panel.py:29
+#: dashboards/project/overview/templates/overview/usage.html:6
+#: dashboards/project/volumes/tabs.py:27
+msgid "Overview"
+msgstr "概要"
+
+#: dashboards/admin/networks/ports/tabs.py:42
+#: dashboards/project/networks/ports/tabs.py:42
+msgid "Unable to retrieve port details."
+msgstr "ポートの詳細を取得できません。"
+
+#: dashboards/admin/networks/ports/views.py:49
+#: dashboards/admin/networks/subnets/views.py:49
+#: dashboards/project/networks/subnets/views.py:54
+msgid "Unable to retrieve network."
+msgstr "ネットワークを取得できません。"
+
+#: dashboards/admin/networks/ports/views.py:82
+msgid "Unable to retrieve port details"
+msgstr "ポートの詳細を取得できません"
+
+#: dashboards/admin/networks/subnets/forms.py:43
+#, python-format
+msgid "Failed to retrieve network %s for a subnet"
+msgstr "サブネットのネットワーク %s の取得に失敗しました"
+
+#: dashboards/admin/networks/subnets/tables.py:32
+#: dashboards/project/networks/subnets/tables.py:44
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:6
+msgid "Subnet"
+msgstr "サブネット"
+
+#: dashboards/admin/networks/subnets/tables.py:33
+#: dashboards/admin/networks/subnets/tables.py:81
+#: dashboards/project/networks/subnets/tables.py:45
+#: dashboards/project/networks/subnets/tables.py:104
+msgid "Subnets"
+msgstr "サブネット"
+
+#: dashboards/admin/networks/subnets/tables.py:49
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:8
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:23
+#: dashboards/admin/networks/templates/networks/subnets/create.html:3
+#: dashboards/admin/networks/templates/networks/subnets/create.html:6
+#: dashboards/project/networks/workflows.py:53
+#: dashboards/project/networks/subnets/tables.py:61
+#: dashboards/project/networks/templates/networks/subnets/_create.html:8
+#: dashboards/project/networks/templates/networks/subnets/_create.html:23
+#: dashboards/project/networks/templates/networks/subnets/create.html:3
+#: dashboards/project/networks/templates/networks/subnets/create.html:6
+msgid "Create Subnet"
+msgstr "サブネットの作成"
+
+#: dashboards/admin/networks/subnets/tables.py:60
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:7
+#: dashboards/project/networks/subnets/tables.py:72
+#: dashboards/project/networks/templates/networks/subnets/_update.html:7
+msgid "Edit Subnet"
+msgstr "サブネットの編集"
+
+#: dashboards/admin/networks/subnets/tables.py:72
+#: dashboards/project/access_and_security/security_groups/forms.py:91
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:15
+msgid "CIDR"
+msgstr "CIDR"
+
+#: dashboards/admin/networks/subnets/tables.py:73
+#: dashboards/project/networks/workflows.py:66
+#: dashboards/project/networks/subnets/forms.py:53
+#: dashboards/project/networks/subnets/tables.py:85
+msgid "IP Version"
+msgstr "IP バージョン"
+
+#: dashboards/admin/networks/subnets/tables.py:74
+#: dashboards/project/networks/subnets/forms.py:54
+#: dashboards/project/networks/subnets/forms.py:104
+#: dashboards/project/networks/subnets/tables.py:86
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:19
+msgid "Gateway IP"
+msgstr "ゲートウェイ IP"
+
+#: dashboards/admin/networks/subnets/views.py:82
+#: dashboards/project/networks/subnets/views.py:86
+msgid "Unable to retrieve subnet details"
+msgstr "サブネットの詳細を取得できません。"
+
+#: dashboards/admin/networks/templates/networks/_create.html:18
+#: dashboards/project/networks/templates/networks/_create.html:17
+msgid "Select a name for your network."
+msgstr "ネットワークの名前を選択してください。"
+
+#: dashboards/admin/networks/templates/networks/_update.html:16
+#: dashboards/admin/networks/templates/networks/ports/_update.html:21
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:25
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:17
+#: dashboards/project/instances/templates/instances/_update.html:16
+#: dashboards/project/networks/templates/networks/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_update.html:25
+#: dashboards/settings/ec2/templates/ec2/download_form.html:17
+#: dashboards/settings/project/templates/project/_openrc.html:24
+#: dashboards/settings/user/templates/user/_settings.html:17
+msgid "Description:"
+msgstr "説明:"
+
+#: dashboards/admin/networks/templates/networks/_update.html:17
+#: dashboards/project/networks/templates/networks/_update.html:17
+msgid "You may update the editable properties of your network here."
+msgstr "ここからネットワークの編集可能なプロパティーを更新できます。"
+
+#: dashboards/admin/networks/templates/networks/_update.html:22
+#: dashboards/admin/networks/templates/networks/ports/_update.html:27
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:31
+#: dashboards/project/instances/templates/instances/_update.html:22
+#: dashboards/project/networks/templates/networks/_update.html:22
+#: dashboards/project/networks/templates/networks/subnets/_update.html:31
+msgid "Save Changes"
+msgstr "変更の保存"
+
+#: dashboards/admin/networks/templates/networks/update.html:3
+#: dashboards/admin/networks/templates/networks/update.html:6
+#: dashboards/project/networks/templates/networks/update.html:3
+#: dashboards/project/networks/templates/networks/update.html:6
+msgid "Update Network"
+msgstr "ネットワークの更新"
+
+#: dashboards/admin/networks/templates/networks/ports/_create.html:18
+msgid ""
+"You can create a port for the network. If you specify device ID to be "
+"attached, the device specified will be attached to the port created."
+msgstr ""
+"ネットワークのポートを作成できます。接続するデバイス ID を指定すると、指定さ"
+"れたデバイスが作成されたポートに接続されます。"
+
+#: dashboards/admin/networks/templates/networks/ports/_update.html:22
+msgid "You may update the editable properties of your port here."
+msgstr "ここからポートの編集可能なプロパティーを更新できます。"
+
+#: dashboards/admin/networks/templates/networks/ports/update.html:3
+#: dashboards/admin/networks/templates/networks/ports/update.html:6
+msgid "Update Port"
+msgstr "ポートの更新"
+
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:18
+#: dashboards/project/networks/templates/networks/subnets/_create.html:18
+msgid ""
+"You can create a subnet for the network. Any network address can be "
+"specified unless the network address does not overlap other subnets in the "
+"network."
+msgstr ""
+"ネットワークのサブネットを作成できます。ネットワークアドレスがネットワークに"
+"あるサブネットと重ならない限り、あらゆるネットワークアドレスを指定できます。"
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:14
+#: dashboards/project/networks/workflows.py:58
+#: dashboards/project/networks/subnets/forms.py:45
+#: dashboards/project/networks/subnets/tables.py:84
+#: dashboards/project/networks/templates/networks/subnets/_update.html:14
+msgid "Network Address"
+msgstr "ネットワークアドレス"
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:17
+#: dashboards/project/networks/templates/networks/subnets/_update.html:16
+msgid "IP version"
+msgstr "IP バージョン"
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:26
+#: dashboards/project/networks/templates/networks/subnets/_update.html:26
+msgid "You may update the editable properties of your subnet here."
+msgstr "ここからサブネットの編集可能なプロパティーを更新できます。"
+
+#: dashboards/admin/networks/templates/networks/subnets/index.html:3
+#: dashboards/admin/networks/templates/networks/subnets/index.html:6
+#: dashboards/project/networks/templates/networks/detail.html:3
+msgid "Network Detail"
+msgstr "ネットワークの詳細"
+
+#: dashboards/admin/networks/templates/networks/subnets/update.html:3
+#: dashboards/admin/networks/templates/networks/subnets/update.html:6
+#: dashboards/project/networks/templates/networks/subnets/update.html:3
+#: dashboards/project/networks/templates/networks/subnets/update.html:6
+msgid "Update Subnet"
+msgstr "サブネットの更新"
+
+#: dashboards/admin/overview/templates/overview/usage.html:3
+msgid "Usage Overview"
+msgstr "使用状況"
+
+#: dashboards/admin/overview/templates/overview/usage.html:12
+msgid "Monitoring"
+msgstr "監視"
+
+#: dashboards/admin/projects/panel.py:29
+#: dashboards/admin/projects/tables.py:66
+#: dashboards/admin/projects/tables.py:95
+#: dashboards/admin/projects/templates/projects/index.html:8
+#: templates/403.html:24 templates/404.html:23 templates/500.html:23
+msgid "Projects"
+msgstr "プロジェクト"
+
+#: dashboards/admin/projects/tables.py:19
+msgid "Modify Users"
+msgstr "ユーザーの変更"
+
+#: dashboards/admin/projects/tables.py:32
+msgid "View Usage"
+msgstr "使用状況の表示"
+
+#: dashboards/admin/projects/tables.py:39
+#: dashboards/admin/projects/templates/projects/_create.html:8
+#: dashboards/admin/projects/templates/projects/_create.html:23
+#: dashboards/admin/projects/templates/projects/create.html:6
+msgid "Create Project"
+msgstr "プロジェクトの作成"
+
+#: dashboards/admin/projects/tables.py:46
+#: dashboards/admin/projects/workflows.py:269
+#: dashboards/admin/projects/templates/projects/update.html:3
+#: dashboards/admin/projects/templates/projects/update.html:6
+msgid "Edit Project"
+msgstr "プロジェクトの編集"
+
+#: dashboards/admin/projects/tables.py:90
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:60
+#: dashboards/project/networks/templates/networks/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:15
+msgid "Project ID"
+msgstr "プロジェクト ID"
+
+#: dashboards/admin/projects/tables.py:91
+#: dashboards/admin/projects/workflows.py:76
+#: dashboards/admin/projects/workflows.py:251
+#: dashboards/admin/services/tables.py:42 dashboards/admin/users/tables.py:40
+#: dashboards/admin/users/tables.py:115
+msgid "Enabled"
+msgstr "有効化しました"
+
+#: dashboards/admin/projects/tables.py:104
+msgid "Remove"
+msgstr "削除します"
+
+#: dashboards/admin/projects/tables.py:105
+msgid "Removed"
+msgstr "削除しました"
+
+#: dashboards/admin/projects/tables.py:106 dashboards/admin/users/tables.py:41
+#: dashboards/admin/users/tables.py:75
+#: dashboards/project/instances/workflows.py:39
+msgid "User"
+msgstr "ユーザー"
+
+#: dashboards/admin/projects/tables.py:107 dashboards/admin/users/panel.py:29
+#: dashboards/admin/users/tables.py:42 dashboards/admin/users/tables.py:76
+#: dashboards/admin/users/tables.py:122
+#: dashboards/admin/users/templates/users/index.html:8
+msgid "Users"
+msgstr "ユーザー"
+
+#: dashboards/admin/projects/tables.py:125
+msgid "Unable to retrieve role information."
+msgstr "役割の情報を取得できません。"
+
+#: dashboards/admin/projects/tables.py:130
+msgid "Roles"
+msgstr "役割"
+
+#: dashboards/admin/projects/tables.py:134
+msgid "Users For Project"
+msgstr "プロジェクトのユーザー"
+
+#: dashboards/admin/projects/tables.py:142
+msgid "Add To Project"
+msgstr "プロジェクトへの追加"
+
+#: dashboards/admin/projects/tables.py:154
+msgid "Add New Users"
+msgstr "新規ユーザーの追加"
+
+#: dashboards/admin/projects/views.py:67
+msgid "Unable to retrieve project information."
+msgstr "プロジェクトの情報を取得できません。"
+
+#: dashboards/admin/projects/views.py:87
+msgid "Unable to retrieve project list."
+msgstr "プロジェクト一覧を取得できません。"
+
+#: dashboards/admin/projects/views.py:110
+msgid "Unable to retrieve users."
+msgstr "ユーザーを取得できません。"
+
+#: dashboards/admin/projects/views.py:154
+msgid "Unable to retrieve default quota values."
+msgstr "クォータの初期値を取得できません。"
+
+#: dashboards/admin/projects/views.py:182
+msgid "Unable to retrieve project details."
+msgstr "プロジェクトの詳細を取得できません。"
+
+#: dashboards/admin/projects/workflows.py:37
+msgid "Injected File Content Bytes"
+msgstr "挿入されたファイルのバイト数"
+
+#: dashboards/admin/projects/workflows.py:38
+msgid "Metadata Items"
+msgstr "メタデータ項目"
+
+#: dashboards/admin/projects/workflows.py:41
+msgid "Injected Files"
+msgstr "挿入されたファイル"
+
+#: dashboards/admin/projects/workflows.py:44
+#: dashboards/admin/volumes/panel.py:9 dashboards/admin/volumes/tables.py:15
+#: dashboards/admin/volumes/templates/volumes/index.html:3
+#: dashboards/admin/volumes/templates/volumes/index.html:6
+#: dashboards/project/volumes/panel.py:25
+#: dashboards/project/volumes/tables.py:38
+#: dashboards/project/volumes/tables.py:171
+#: dashboards/project/volumes/tables.py:183
+#: dashboards/project/volumes/templates/volumes/index.html:3
+#: dashboards/project/volumes/templates/volumes/index.html:6
+msgid "Volumes"
+msgstr "ボリューム"
+
+#: dashboards/admin/projects/workflows.py:45
+msgid "Gigabytes"
+msgstr "ギガバイト"
+
+#: dashboards/admin/projects/workflows.py:46
+msgid "RAM (MB)"
+msgstr "メモリー (MB)"
+
+#: dashboards/admin/projects/workflows.py:47
+#: dashboards/project/access_and_security/floating_ips/tables.py:50
+#: dashboards/project/access_and_security/floating_ips/tables.py:128
+msgid "Floating IPs"
+msgstr "Floating IP"
+
+#: dashboards/admin/projects/workflows.py:50
+msgid "Quota"
+msgstr "クォータ"
+
+#: dashboards/admin/projects/workflows.py:52
+msgid "From here you can set quotas (max limits) for the project."
+msgstr "ここからプロジェクトのクォータ (最大制限) を設定できます。"
+
+#: dashboards/admin/projects/workflows.py:81
+#: dashboards/admin/projects/workflows.py:254
+msgid "Project Info"
+msgstr "プロジェクトの情報"
+
+#: dashboards/admin/projects/workflows.py:82
+#: dashboards/admin/projects/templates/projects/_create.html:18
+msgid "From here you can create a new project to organize users."
+msgstr "ここから、ユーザーを整理するために新しいプロジェクトを作成できます。"
+
+#: dashboards/admin/projects/workflows.py:101
+msgid "Unable to retrieve user list. Please try again later."
+msgstr "ユーザー一覧を取得できません。後ほど再びお試しください。"
+
+#: dashboards/admin/projects/workflows.py:155
+#: dashboards/admin/projects/templates/projects/_update_members.html:16
+msgid "Project Members"
+msgstr "プロジェクトのメンバー"
+
+#: dashboards/admin/projects/workflows.py:169
+#: dashboards/admin/users/views.py:47
+msgid "Unable to retrieve user list."
+msgstr "ユーザー一覧を取得できません。"
+
+#: dashboards/admin/projects/workflows.py:180
+msgid "Add Project"
+msgstr "プロジェクトの追加"
+
+#: dashboards/admin/projects/workflows.py:181
+msgid "Finish"
+msgstr "完了"
+
+#: dashboards/admin/projects/workflows.py:182
+#, python-format
+msgid "Created new project \"%s\"."
+msgstr "新規プロジェクト \"%s\" を作成しました。"
+
+#: dashboards/admin/projects/workflows.py:183
+#, python-format
+msgid "Unable to create project \"%s\"."
+msgstr "プロジェクト \"%s\" を作成できません。"
+
+#: dashboards/admin/projects/workflows.py:227
+#, python-format
+msgid "Failed to add %s project members and set project quotas."
+msgstr ""
+"%s プロジェクトメンバーの追加とプロジェクトのクォータの設定に失敗しました。"
+
+#: dashboards/admin/projects/workflows.py:246
+msgid "Unable to set project quotas."
+msgstr "プロジェクトのクォータを設定できません。"
+
+#: dashboards/admin/projects/workflows.py:256
+msgid "From here you can edit the project details."
+msgstr "ここからプロジェクトの詳細を編集できます。"
+
+#: dashboards/admin/projects/workflows.py:271
+#, python-format
+msgid "Modified project \"%s\"."
+msgstr "プロジェクト \"%s\" を変更しました。"
+
+#: dashboards/admin/projects/workflows.py:272
+#, python-format
+msgid "Unable to modify project \"%s\"."
+msgstr "プロジェクト \"%s\" を変更できません。"
+
+#: dashboards/admin/projects/workflows.py:342
+#, python-format
+msgid "Failed to modify %s project members and update project quotas."
+msgstr ""
+"%s プロジェクトのメンバーの変更とプロジェクトのクォータの更新に失敗しました"
+
+#: dashboards/admin/projects/workflows.py:363
+msgid ""
+"Modified project information and members, but unable to modify project "
+"quotas."
+msgstr ""
+"プロジェクトの情報とメンバーを変更しましたが、プロジェクトのクォータを変更で"
+"きません。"
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:8
+#: dashboards/admin/projects/templates/projects/add_user.html:3
+#: dashboards/admin/projects/templates/projects/add_user.html:6
+msgid "Add User To Project"
+msgstr "プロジェクトへの追加"
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:18
+msgid "Select the user role for the project."
+msgstr "プロジェクトに対するユーザーの役割を選択します。"
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:23
+msgid "Add"
+msgstr "追加"
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:7
+#, python-format
+msgid "Create User for project '%(tenant_name)s'."
+msgstr "プロジェクト '%(tenant_name)s' のユーザーを作成します。"
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:18
+msgid "From here you can create a new user to add to this project."
+msgstr "ここからこのプロジェクトに追加する新規ユーザーを作成できます。"
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:23
+#: dashboards/admin/users/tables.py:20
+#: dashboards/admin/users/templates/users/_create.html:7
+#: dashboards/admin/users/templates/users/_create.html:22
+#: dashboards/admin/users/templates/users/create.html:7
+msgid "Create User"
+msgstr "ユーザーの作成"
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:7
+#: dashboards/admin/projects/templates/projects/_quotas.html:22
+msgid "Update Quota"
+msgstr "クォータの更新"
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:17
+#, python-format
+msgid ""
+"From here you can edit quotas (max limits) for the project %(tenant.name)s."
+msgstr "プロジェクト %(tenant.name)s のクォータ (上限値) を設定できます。"
+
+#: dashboards/admin/projects/templates/projects/_update.html:8
+#: dashboards/admin/projects/templates/projects/_update.html:23
+#: dashboards/admin/projects/templates/projects/quotas.html:6
+msgid "Update Project"
+msgstr "プロジェクトの更新"
+
+#: dashboards/admin/projects/templates/projects/_update.html:18
+msgid "From here you can edit a project."
+msgstr "プロジェクトを編集できます。"
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:7
+msgid ""
+"From here you can add and remove members to this project from the list of "
+"all available users."
+msgstr ""
+"すべての利用可能なユーザー一覧から、このプロジェクトにメンバーを追加または削"
+"除できます。"
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:10
+msgid "All Users"
+msgstr "すべてのユーザー"
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:25
+#: dashboards/admin/projects/templates/projects/_update_members.html:32
+msgid "No users found."
+msgstr "ユーザーが見つかりませんでした。"
+
+#: dashboards/admin/projects/templates/projects/create_user.html:3
+#: dashboards/admin/projects/templates/projects/create_user.html:6
+msgid "Add New User"
+msgstr "新規ユーザーの追加"
+
+#: dashboards/admin/projects/templates/projects/usage.html:3
+msgid "Project Usage Overview"
+msgstr "プロジェクトの使用量の概要"
+
+#: dashboards/admin/projects/templates/projects/usage.html:7
+msgid "Project Usage"
+msgstr "プロジェクト使用状況"
+
+#: dashboards/admin/projects/templates/projects/users.html:7
+msgid "Users for Project"
+msgstr "所属ユーザー"
+
+#: dashboards/admin/quotas/panel.py:29 dashboards/admin/quotas/tables.py:36
+msgid "Quotas"
+msgstr "クォータ"
+
+#: dashboards/admin/quotas/tables.py:28
+msgid "Quota Name"
+msgstr "クォータ名"
+
+#: dashboards/admin/quotas/tables.py:29
+msgid "Limit"
+msgstr "制限値"
+
+#: dashboards/admin/quotas/views.py:46
+msgid "Unable to get quota info."
+msgstr "クォータ情報を取得できません。"
+
+#: dashboards/admin/quotas/templates/quotas/index.html:8
+msgid "Default Quotas"
+msgstr "デフォルト クォータ"
+
+#: dashboards/admin/services/panel.py:29
+#: dashboards/admin/services/tables.py:47
+#: dashboards/admin/services/templates/services/index.html:8
+msgid "Services"
+msgstr "サービス"
+
+#: dashboards/admin/services/tables.py:37
+msgid "Id"
+msgstr "ID"
+
+#: dashboards/admin/services/tables.py:39
+msgid "Service"
+msgstr "サービス"
+
+#: dashboards/admin/users/forms.py:54
+msgid "Passwords do not match."
+msgstr "パスワードが一致しません。"
+
+#: dashboards/admin/users/forms.py:62 dashboards/admin/users/forms.py:115
+#: dashboards/admin/users/tables.py:108
+msgid "User Name"
+msgstr "ユーザー名"
+
+#: dashboards/admin/users/forms.py:63 dashboards/admin/users/forms.py:116
+#: dashboards/admin/users/tables.py:109
+msgid "Email"
+msgstr "メール"
+
+#: dashboards/admin/users/forms.py:65 dashboards/admin/users/forms.py:117
+msgid "Password"
+msgstr "パスワード"
+
+#: dashboards/admin/users/forms.py:70 dashboards/admin/users/forms.py:124
+msgid "Confirm Password"
+msgstr "パスワード (確認)"
+
+#: dashboards/admin/users/forms.py:73 dashboards/admin/users/forms.py:127
+msgid "Primary Project"
+msgstr "プライマリ プロジェクト"
+
+#: dashboards/admin/users/forms.py:75
+msgid "Role"
+msgstr "ロール"
+
+#: dashboards/admin/users/forms.py:96
+#, python-format
+msgid "User \"%s\" was successfully created."
+msgstr "ユーザー \"%s\" を作成しました。"
+
+#: dashboards/admin/users/forms.py:106
+msgid "Unable to add userto primary project."
+msgstr "プライマリ プロジェクトへユーザーを追加できません。"
+
+#: dashboards/admin/users/forms.py:110
+msgid "Unable to create user."
+msgstr "ユーザーを作成できません。"
+
+#: dashboards/admin/users/forms.py:151
+msgid "name"
+msgstr "名前"
+
+#: dashboards/admin/users/forms.py:151
+msgid "email"
+msgstr "メール"
+
+#: dashboards/admin/users/forms.py:160
+msgid "primary project"
+msgstr "主プロジェクト"
+
+#: dashboards/admin/users/forms.py:173
+#, python-format
+msgid "The user %s has no role defined for"
+msgstr "ユーザー %s が次のものに対して定義された役割がありません"
+
+#: dashboards/admin/users/forms.py:181
+msgid "password"
+msgstr "パスワード"
+
+#: dashboards/admin/users/forms.py:190
+msgid "User has been updated successfully."
+msgstr "ユーザーが正常に更新されました。"
+
+#: dashboards/admin/users/forms.py:194
+#, python-format
+msgid "Unable to update %(attributes)s for the user."
+msgstr "ユーザーの %(attributes)s を更新できません。"
+
+#: dashboards/admin/users/tables.py:32
+#: dashboards/project/images_and_snapshots/images/tables.py:68
+msgid "Edit"
+msgstr "編集"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Enable"
+msgstr "有効化"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Disable"
+msgstr "無効化"
+
+#: dashboards/admin/users/tables.py:40
+msgid "Disabled"
+msgstr "無効化しました"
+
+#: dashboards/admin/users/tables.py:63
+msgid "You cannot disable the user you are currently logged in as."
+msgstr "現在ログインしているユーザーを無効化できません。"
+
+#: dashboards/admin/users/tables.py:114
+msgid "User ID"
+msgstr "ユーザー ID"
+
+#: dashboards/admin/users/views.py:70
+msgid "Unable to update user."
+msgstr "ユーザーを更新できません。"
+
+#: dashboards/admin/users/views.py:104
+msgid "Unable to retrieve user roles."
+msgstr "ユーザーの役割を取得できません。"
+
+#: dashboards/admin/users/templates/users/_create.html:17
+msgid "From here you can create a new user and assign them to a project."
+msgstr "ここから、新規ユーザーを作成でき、プロジェクトに割り当てられます。"
+
+#: dashboards/admin/users/templates/users/_update.html:7
+#: dashboards/admin/users/templates/users/_update.html:22
+#: dashboards/admin/users/templates/users/update.html:7
+msgid "Update User"
+msgstr "ユーザーの更新"
+
+#: dashboards/admin/users/templates/users/_update.html:17
+msgid ""
+"From here you can edit the user's details, including their default project."
+msgstr "ここから、ユーザーの初期プロジェクトを含め、詳細を編集できます。"
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:3
+#: dashboards/project/volumes/templates/volumes/detail.html:3
+msgid "Volume Details"
+msgstr "ボリュームの詳細"
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:6
+#: dashboards/project/volumes/templates/volumes/detail.html:6
+msgid "Volume Detail"
+msgstr "ボリュームの詳細"
+
+#: dashboards/project/dashboard.py:24
+msgid "Manage Compute"
+msgstr "Compute の管理"
+
+#: dashboards/project/dashboard.py:35
+msgid "Object Store"
+msgstr "オブジェクトストア"
+
+#: dashboards/project/access_and_security/panel.py:26
+#: dashboards/project/instances/workflows.py:348
+msgid "Access & Security"
+msgstr "アクセスとセキュリティ"
+
+#: dashboards/project/access_and_security/views.py:51
+msgid "Unable to retrieve keypair list."
+msgstr "キーペアリストを取得できません。"
+
+#: dashboards/project/access_and_security/views.py:60
+#: dashboards/project/access_and_security/security_groups/views.py:74
+msgid "Unable to retrieve security groups."
+msgstr "セキュリティグループを取得できません。"
+
+#: dashboards/project/access_and_security/views.py:69
+#: dashboards/project/access_and_security/floating_ips/workflows.py:49
+msgid "Unable to retrieve floating IP addresses."
+msgstr "Floating IP アドレスを取得できません。"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:32
+msgid "Pool"
+msgstr "プール"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:43
+#, python-format
+msgid "Allocated Floating IP %(ip)s."
+msgstr "Floating IP %(ip)s を割り当てました。"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:47
+msgid "Unable to allocate Floating IP."
+msgstr "Floating IP を割り当てられません。"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:37
+msgid "Allocate IP To Project"
+msgstr "IP をプロジェクトに割り当てます"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:47
+msgid "Release"
+msgstr "解放"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:48
+msgid "Released"
+msgstr "解放しました"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:49
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:22
+msgid "Floating IP"
+msgstr "Floating IP"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:6
+#: dashboards/project/instances/tables.py:219
+msgid "Associate Floating IP"
+msgstr "Floating IP の割り当て"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:76
+msgid "Disassociate Floating IP"
+msgstr "Floating IP の割り当て解除"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:90
+#, python-format
+msgid "Successfully disassociated Floating IP: %s"
+msgstr "Floating IP の割り当て解除に成功しました: %s"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:94
+msgid "Unable to disassociate floating IP."
+msgstr "Floating IP の割り当てを解除できません。"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:114
+#: dashboards/project/access_and_security/floating_ips/workflows.py:36
+#: dashboards/project/instances/tables.py:69
+#: dashboards/project/instances/tables.py:89
+#: dashboards/project/instances/tables.py:106
+#: dashboards/project/instances/tables.py:135
+#: dashboards/project/volumes/tables.py:206
+msgid "Instance"
+msgstr "インスタンス"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:117
+msgid "Floating IP Pool"
+msgstr "Floating IP プール"
+
+#: dashboards/project/access_and_security/floating_ips/views.py:65
+msgid "Unable to retrieve floating IP pools."
+msgstr "Floating IP プールを取得できません。"
+
+#: dashboards/project/access_and_security/floating_ips/views.py:68
+msgid "No floating IP pools available."
+msgstr "Floating IP プールがありません。"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:40
+msgid "Select the IP address you wish to associate with the selected instance."
+msgstr "選択されたインスタンスと割り当てたい IP アドレスを選択します。"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:53
+msgid "Select an IP address"
+msgstr "IP アドレスの選択"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:55
+msgid "No IP addresses available"
+msgstr "利用可能な IP アドレスがありません"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:76
+#: dashboards/project/volumes/forms.py:160
+msgid "Select an instance"
+msgstr "インスタンスを選択して下さい"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:78
+#: dashboards/project/volumes/forms.py:162
+msgid "No instances available"
+msgstr "インスタンスがありません"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:97
+msgid "Manage Floating IP Associations"
+msgstr "Floating IP の割り当ての管理"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:98
+msgid "Associate"
+msgstr "割り当て"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:99
+#, python-format
+msgid "IP address %s associated."
+msgstr "IP アドレス %s を割り当てました。"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:100
+#, python-format
+msgid "Unable to associate IP address %s."
+msgstr "IP アドレス %s を割り当てられません。"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:38
+#: dashboards/project/access_and_security/keypairs/forms.py:49
+#: dashboards/project/access_and_security/keypairs/tables.py:52
+msgid "Keypair Name"
+msgstr "キーペア名"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:40
+msgid ""
+"Keypair names may only contain letters, numbers, underscores and hyphens."
+msgstr ""
+"キーペア名では、アルファベット、数字、アンダースコア、ハイフンだけが使用でき"
+"ます。"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:51
+msgid "Public Key"
+msgstr "公開鍵"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:60
+#, python-format
+msgid "Successfully imported public key: %s"
+msgstr "公開鍵を正常に取り込みました: %s"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:65
+msgid "Unable to import keypair."
+msgstr "キーペアをインポートできません。"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:30
+#: dashboards/project/instances/tables.py:295
+#: dashboards/project/instances/workflows.py:335
+msgid "Keypair"
+msgstr "キーペア"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:31
+#: dashboards/project/access_and_security/keypairs/tables.py:60
+msgid "Keypairs"
+msgstr "キーペア"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:39
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html:6
+msgid "Import Keypair"
+msgstr "キーペアの取り込み"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:46
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html:6
+msgid "Create Keypair"
+msgstr "キーペアの作成"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:53
+msgid "Fingerprint"
+msgstr "フィンガープリント"
+
+#: dashboards/project/access_and_security/keypairs/views.py:74
+#, python-format
+msgid "Unable to create keypair: %(exc)s"
+msgstr "キーペアを作成できません: %(exc)s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:46
+#, python-format
+msgid "Successfully created security group: %s"
+msgstr "セキュリティグループ %s を正常に作成しました。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:52
+msgid "Unable to create security group."
+msgstr "セキュリティグループを作成できません。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:57
+#: dashboards/project/access_and_security/security_groups/tables.py:93
+msgid "IP Protocol"
+msgstr "IP プロトコル"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:61
+msgid "The protocol which this rule should be applied to."
+msgstr "このルールが適用されるプロトコル。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:65
+#: dashboards/project/access_and_security/security_groups/forms.py:71
+#: dashboards/project/access_and_security/security_groups/tables.py:95
+msgid "From Port"
+msgstr "ポート番号 (下限)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:66
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP type in the range (-1: 255)"
+msgstr ""
+"TCP/UDP: 1 から 65535 の間の整数を入力してください。 ICMP: ICMP 種別として範"
+"囲 (-1: 255) の値を入力してください。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:72
+#: dashboards/project/images_and_snapshots/images/tables.py:115
+msgid "Type"
+msgstr "種別"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:74
+#: dashboards/project/access_and_security/security_groups/forms.py:80
+#: dashboards/project/access_and_security/security_groups/tables.py:96
+msgid "To Port"
+msgstr "ポート番号 (上限)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:75
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP code in the range (-1: 255)"
+msgstr ""
+"TCP/UDP: 1 から 65535 の間の整数を入力してください。 ICMP: ICMP コードとして"
+"範囲 (-1: 255) の値を入力してください。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:81
+msgid "Code"
+msgstr "コード"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:84
+msgid "Source Group"
+msgstr "元グループ"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:86
+msgid ""
+"To specify an allowed IP range, select CIDR. To allow access from all "
+"members of another security group select Source Group."
+msgstr ""
+"許可 IP 範囲を指定するには、CIDR を選択してください。他のセキュリティグループ"
+"のすべてのメンバーからアクセスを許可するには、ソースグループを選択してくださ"
+"い。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:94
+msgid "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+msgstr "ネットワークアドレス (例: 192.168.0.0/24)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:121
+msgid "The ICMP type is invalid."
+msgstr "ICMP タイプが無効です。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:124
+msgid "The ICMP code is invalid."
+msgstr "ICMP コードが無効です。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:127
+msgid "The ICMP type not in range (-1, 255)"
+msgstr "ICMP 形式が範囲 (-1, 255) にありません"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:130
+msgid "The ICMP code not in range (-1, 255)"
+msgstr "ICMP コードが範囲 (-1, 255) にありません"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:134
+msgid "The \"from\" port number is invalid."
+msgstr "「下限」ポート番号が無効です。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:137
+msgid "The \"to\" port number is invalid."
+msgstr "「上限」ポート番号が無効です。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:140
+msgid ""
+"The \"to\" port number must be greater than or equal to the \"from\" port "
+"number."
+msgstr "「上限」ポート番号は「下限」ポート番号以上でなければいけません。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:146
+msgid "Either CIDR or Source Group may be specified, but not both."
+msgstr "CIDR またはソースグループが指定できますが、両方はできません。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:168
+#, python-format
+msgid "Successfully added rule: %s"
+msgstr "ルールを正常に追加しました: %s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:173
+msgid "Unable to add rule to security group."
+msgstr "ルールをセキュリティグループに追加できません。"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:31
+msgid "Security Group"
+msgstr "セキュリティグループ"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:32
+#: dashboards/project/access_and_security/security_groups/tables.py:66
+#: dashboards/project/instances/workflows.py:340
+#: dashboards/project/instances/templates/instances/_detail_overview.html:49
+msgid "Security Groups"
+msgstr "セキュリティグループ"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:45
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html:6
+msgid "Create Security Group"
+msgstr "セキュリティグループの作成"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:52
+msgid "Edit Rules"
+msgstr "ルールの編集"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:72
+msgid "Rule"
+msgstr "ルール"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:73
+msgid "Rules"
+msgstr "ルール"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:97
+msgid "Source"
+msgstr "接続元"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:107
+msgid "Security Group Rules"
+msgstr "セキュリティグループ"
+
+#: dashboards/project/access_and_security/security_groups/views.py:60
+msgid "Unable to retrieve security group."
+msgstr "セキュリティグループ情報を取得できません。"
+
+#: dashboards/project/access_and_security/security_groups/views.py:80
+#, python-format
+msgid "%s (current)"
+msgstr "%s (カレント)"
+
+#: dashboards/project/access_and_security/templates/access_and_security/index.html:6
+msgid "Access &amp; Security"
+msgstr "アクセスとセキュリティ"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:8
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html:3
+msgid "Allocate Floating IP"
+msgstr "Floating IP の確保"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:18
+msgid "Allocate a floating IP from a given floating ip pool."
+msgstr "指定した Floating IP プールから Floating IP を確保します。"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:20
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:19
+msgid "Project Quotas"
+msgstr "プロジェクトのクォータ"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:31
+msgid "Allocate IP"
+msgstr "IP の確保"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:17
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:17
+msgid ""
+"Keypairs are ssh credentials which are injected into images when they are "
+"launched. Creating a new key pair registers the public key and downloads the "
+"private key (a .pem file)."
+msgstr ""
+"キーペアは、イメージが起動するときに、イメージに挿入される SSH クレディンシャ"
+"ルです。新しいキーペアを作成することにより、公開鍵を登録し、秘密鍵 (.pem ファ"
+"イル) をダウンロードできます。"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:18
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:18
+msgid "Protect and use the key as you would any normal ssh private key."
+msgstr "通常の SSH 秘密鍵と同じように保護および使用します。"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:6
+msgid "Download Keypair"
+msgstr "キーペアのダウンロード"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:11
+#, python-format
+msgid ""
+"The keypair &quot;%(keypair_name)s&quot; should download automatically. If "
+"not use the link below."
+msgstr ""
+"以下のリンクを使用しなければ、キーペア &quot;%(keypair_name)s&quot; が自動的"
+"にダウンロードされます。"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:15
+#, python-format
+msgid "Download keypair &quot;%(keypair_name)s&quot;"
+msgstr "キーペア &quot;%(keypair_name)s&quot; のダウンロード"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:18
+msgid "From here you can create a new security group"
+msgstr "ここから新しいセキュリティグループを作成できます"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:9
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html:6
+msgid "Edit Security Group Rules"
+msgstr "セキュリティグループのルールの変更"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:12
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:19
+msgid "Add Rule"
+msgstr "ルールの追加"
+
+#: dashboards/project/containers/browsers.py:26
+msgid "Swift"
+msgstr "Swift"
+
+#: dashboards/project/containers/browsers.py:29
+#: dashboards/project/containers/tables.py:40
+msgid "Container"
+msgstr "コンテナー"
+
+#: dashboards/project/containers/forms.py:39
+msgid "Slash is not an allowed character."
+msgstr "スラッシュ (/) は使用できません。"
+
+#: dashboards/project/containers/forms.py:49
+#: dashboards/project/containers/tables.py:121
+msgid "Container Name"
+msgstr "コンテナー名"
+
+#: dashboards/project/containers/forms.py:57
+msgid "Container created successfully."
+msgstr "コンテナーが正常に作成されました。"
+
+#: dashboards/project/containers/forms.py:68
+msgid "Folder created successfully."
+msgstr "フォルダーが正常に作成されました。"
+
+#: dashboards/project/containers/forms.py:71
+msgid "Unable to create container."
+msgstr "コンテナーを作成できません。"
+
+#: dashboards/project/containers/forms.py:79
+#: dashboards/project/containers/tables.py:253
+msgid "Object Name"
+msgstr "オブジェクト名"
+
+#: dashboards/project/containers/forms.py:81
+msgid "File"
+msgstr "ファイル"
+
+#: dashboards/project/containers/forms.py:95
+msgid "Object was successfully uploaded."
+msgstr "オブジェクトが正常にアップロードされました。"
+
+#: dashboards/project/containers/forms.py:98
+msgid "Unable to upload object."
+msgstr "オブジェクトをアップロードできません。"
+
+#: dashboards/project/containers/forms.py:102
+msgid "Destination container"
+msgstr "宛先コンテナー"
+
+#: dashboards/project/containers/forms.py:106
+msgid "Destination object name"
+msgstr "宛先オブジェクト名"
+
+#: dashboards/project/containers/forms.py:137
+#: dashboards/project/containers/forms.py:163
+msgid "Unable to copy object."
+msgstr "オブジェクトをコピーできません。"
+
+#: dashboards/project/containers/forms.py:153
+#, python-format
+msgid "Copied \"%(orig)s\" to \"%(dest)s\" as \"%(new)s\"."
+msgstr "\"%(orig)s\" を \"%(dest)s\" に \"%(new)s\" としてコピーします。"
+
+#: dashboards/project/containers/panel.py:29
+#: dashboards/project/containers/tables.py:41
+#: dashboards/project/containers/tables.py:128
+#: dashboards/project/containers/templates/containers/index.html:7
+msgid "Containers"
+msgstr "コンテナー"
+
+#: dashboards/project/containers/tables.py:62
+#: dashboards/project/containers/templates/containers/_create.html:7
+#: dashboards/project/containers/templates/containers/_create.html:22
+#: dashboards/project/containers/templates/containers/create.html:6
+msgid "Create Container"
+msgstr "コンテナーの作成"
+
+#: dashboards/project/containers/tables.py:69
+msgid "View Container"
+msgstr "コンテナーの表示"
+
+#: dashboards/project/containers/tables.py:81
+#: dashboards/project/containers/templates/containers/_upload.html:23
+#: dashboards/project/containers/templates/containers/upload.html:3
+msgid "Upload Object"
+msgstr "オブジェクトのアップロード"
+
+#: dashboards/project/containers/tables.py:137
+#: dashboards/project/containers/tables.py:156
+msgid "Object"
+msgstr "オブジェクト"
+
+#: dashboards/project/containers/tables.py:138
+#: dashboards/project/containers/tables.py:157
+#: dashboards/project/containers/tables.py:263
+msgid "Objects"
+msgstr "オブジェクト"
+
+#: dashboards/project/containers/tables.py:149
+msgid "Folder"
+msgstr "フォルダー"
+
+#: dashboards/project/containers/tables.py:150
+msgid "Folders"
+msgstr "フォルダー"
+
+#: dashboards/project/containers/tables.py:163
+msgid "Copy"
+msgstr "コピー"
+
+#: dashboards/project/containers/tables.py:176
+msgid "Download"
+msgstr "ダウンロード"
+
+#: dashboards/project/containers/tables.py:232
+msgid "Create Folder"
+msgstr "フォルダーの作成"
+
+#: dashboards/project/containers/views.py:53
+msgid "Unable to retrieve container list."
+msgstr "コンテナーの一覧を取得できません。"
+
+#: dashboards/project/containers/views.py:82
+msgid "Unable to retrieve object list."
+msgstr "オブジェクトの一覧を取得できません。"
+
+#: dashboards/project/containers/views.py:166
+msgid "Unable to retrieve object."
+msgstr "オブジェクトを取得できません。"
+
+#: dashboards/project/containers/views.py:200
+msgid "Unable to list containers."
+msgstr "コンテナーの一覧を表示できません。"
+
+#: dashboards/project/containers/templates/containers/_copy.html:7
+#: dashboards/project/containers/templates/containers/_copy.html:22
+#: dashboards/project/containers/templates/containers/copy.html:3
+#: dashboards/project/containers/templates/containers/copy.html:6
+msgid "Copy Object"
+msgstr "オブジェクトのコピー"
+
+#: dashboards/project/containers/templates/containers/_copy.html:17
+msgid ""
+"Make a new copy of an existing object to store in this or another container. "
+"You may also specify a path at which the new copy should live inside of the "
+"selected container."
+msgstr ""
+"このコンテナーまたは他のコンテナーに保存するために、既存のオブジェクトの新規"
+"コピーを作成します。選択したコンテナーの中で稼働する、新規コピーのパスを指定"
+"することもできます。"
+
+#: dashboards/project/containers/templates/containers/_create.html:17
+msgid ""
+"A container is a storage compartment for your data and provides a way for "
+"you to organize your data. You can think of a container as a folder in "
+"Windows &reg; or a directory in UNIX &reg;. The primary difference between a "
+"container and these other file system concepts is that containers cannot be "
+"nested. You can, however, create an unlimited number of containers within "
+"your account. Data must be stored in a container so you must have at least "
+"one container defined in your account prior to uploading data."
+msgstr ""
+"コンテナーはデータのストレージの区画です。データを整理する手段を提供します。"
+"Windows &reg; のフォルダーや UNIX &reg; のディレクトリーのようにコンテナーを"
+"考えることができます。コンテナーとこれらのファイルシステムの概念の主な違い"
+"は、コンテナーは入れ子にできないことです。しかしながら、アカウントの中に無制"
+"限のコンテナーを作成できます。データはコンテナーに保存する必要があります。そ"
+"のため、データをアップロードする前に、少なくとも一つのコンテナーをアカウント"
+"に定義する必要があります。"
+
+#: dashboards/project/containers/templates/containers/_upload.html:8
+msgid "Upload Object To Container"
+msgstr "オブジェクトのコンテナーへのアップロード"
+
+#: dashboards/project/containers/templates/containers/_upload.html:18
+msgid ""
+"An object is the basic storage entity and any optional metadata that "
+"represents the files you store in the OpenStack Object Storage system. When "
+"you upload data to OpenStack Object Storage, the data is stored as-is (no "
+"compression or encryption) and consists of a location (container), the "
+"object's name, and any metadata consisting of key/value pairs."
+msgstr ""
+"オブジェクトは、基本的なストレージ・エンティティ、および OpenStack Object "
+"Storage システムに保存するファイルを表現するあらゆるオプションのメタデータで"
+"す。OpenStack Object Storage にデータをアップロードするとき、データはそのまま"
+"(圧縮や暗号化はしない)で保存されます。そして、保存場所(コンテナー)、オブ"
+"ジェクトの名前、キー・バリュー組のあらゆるメタデータから構成されます。"
+
+#: dashboards/project/containers/templates/containers/upload.html:6
+msgid "Upload Objects"
+msgstr "オブジェクトのアップロード"
+
+#: dashboards/project/images_and_snapshots/panel.py:26
+msgid "Images & Snapshots"
+msgstr "イメージ & スナップショット"
+
+#: dashboards/project/images_and_snapshots/views.py:63
+msgid "Unable to retrieve images."
+msgstr "イメージ情報を取得できません。"
+
+#: dashboards/project/images_and_snapshots/views.py:74
+msgid "Unable to retrieve snapshots."
+msgstr "スナップショット情報を取得できません。"
+
+#: dashboards/project/images_and_snapshots/views.py:82
+#: dashboards/project/volumes/forms.py:65
+msgid "Unable to retrieve volume snapshots."
+msgstr "ボリュームのスナップショット情報を取得できません。"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:42
+msgid "Image Location"
+msgstr "イメージの場所"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:43
+msgid "An external (HTTP) URL to load the image from."
+msgstr "イメージを読み込む外部 (HTTP) URL。"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:46
+#: dashboards/project/images_and_snapshots/images/forms.py:130
+#: dashboards/project/images_and_snapshots/images/tables.py:126
+msgid "Format"
+msgstr "形式"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:50
+msgid "AKI - Amazon Kernel Image"
+msgstr "AKI - Amazon カーネル・イメージ"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:53
+msgid "AMI - Amazon Machine Image"
+msgstr "AMI - Amazon マシン・イメージ"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:56
+msgid "ARI - Amazon Ramdisk Image"
+msgstr "ARI - Amazon ラムディスク・イメージ"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:59
+msgid "ISO - Optical Disk Image"
+msgstr "ISO - 光学ディスクイメージ"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:61
+msgid "QCOW2 - QEMU Emulator"
+msgstr "QCOW2 - QEMU エミュレーター"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:68
+msgid "Minimum Disk (GB)"
+msgstr "最小ディスク (GB)"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:69
+#: dashboards/project/images_and_snapshots/images/forms.py:76
+msgid ""
+"The minimum disk size required to boot the image. If unspecified, this value "
+"defaults to 0 (no minimum)."
+msgstr ""
+"イメージを起動するために必要となる最小ディスク容量。指定されなければ、この値"
+"の初期値は 0 (最小値なし) です。"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:75
+msgid "Minimum Ram (MB)"
+msgstr "最小メモリー (MB)"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:82
+#: dashboards/project/images_and_snapshots/images/forms.py:134
+#: dashboards/project/images_and_snapshots/images/tables.py:123
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:15
+msgid "Public"
+msgstr "パブリック"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:106
+#, python-format
+msgid "Your image %s has been queued for creation."
+msgstr "イメージ %s が作成のためにキューに入れられました。"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:110
+msgid "Unable to create new image."
+msgstr "新しいイメージを作成できません。"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:116
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:48
+msgid "Kernel ID"
+msgstr "カーネル ID"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:121
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:52
+msgid "Ramdisk ID"
+msgstr "RAM ディスク ID"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:126
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:44
+msgid "Architecture"
+msgstr "アーキテクチャー"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:138
+#, python-format
+msgid "Unable to update image \"%s\"."
+msgstr "イメージ \"%s\" を更新できません。"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:162
+msgid "Image was successfully updated."
+msgstr "イメージが正常に更新されました。"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:34
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:33
+#: dashboards/project/instances/workflows.py:455
+msgid "Launch"
+msgstr "起動"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:46
+#: dashboards/project/images_and_snapshots/images/tables.py:82
+#: dashboards/project/instances/workflows.py:168
+#: dashboards/project/instances/workflows.py:173
+msgid "Image"
+msgstr "イメージ"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:61
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:31
+msgid "Create Image"
+msgstr "イメージの作成"
+
+#: dashboards/project/images_and_snapshots/images/tabs.py:38
+msgid "Unable to retrieve image details."
+msgstr "イメージの詳細を取得できません。"
+
+#: dashboards/project/images_and_snapshots/images/views.py:61
+msgid "Unable to retrieve image."
+msgstr "イメージ情報を取得できません。"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:37
+msgid "Instance ID"
+msgstr "インスタンス ID"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:40
+#: dashboards/project/volumes/forms.py:193
+msgid "Snapshot Name"
+msgstr "スナップショット名"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:50
+#, python-format
+msgid "Snapshot \"%(name)s\" created for instance \"%(inst)s\""
+msgstr ""
+"スナップショット \"%(name)s\" がインスタンス \"%(inst)s\" に対して作成されま"
+"した"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:56
+msgid "Unable to create snapshot."
+msgstr "スナップショットを作成できません。"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:48
+#: dashboards/project/instances/workflows.py:107
+#: dashboards/project/instances/workflows.py:169
+msgid "Snapshot"
+msgstr "スナップショット"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:49
+msgid "Snapshots"
+msgstr "スナップショット"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:55
+msgid "Instance Snapshots"
+msgstr "インスタンスのスナップショット"
+
+#: dashboards/project/images_and_snapshots/snapshots/views.py:53
+msgid "Unable to retrieve instance."
+msgstr "インスタンス情報を取得できません。"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:6
+msgid "Images &amp; Snapshots"
+msgstr "イメージとスナップショット"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:6
+msgid "Create An Image"
+msgstr "イメージの作成"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:18
+msgid "Specify an image to upload to the Image Service."
+msgstr "イメージサービスにアップロードするイメージを指定します。"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:21
+msgid ""
+"Currently only images available via an HTTP URL are supported. The image "
+"location must be accessible to the Image Service. Compressed image binaries "
+"are supported (.zip and .tar.gz.)"
+msgstr ""
+"現在は HTTP URL 経由で利用可能なイメージのみがサポートされます。イメージの場"
+"所は Image Service にアクセス可能である必要があります。圧縮イメージがサポート"
+"されます (.zip および .tar.gz.)。"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:24
+msgid "Please note: "
+msgstr "注意: "
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:25
+#, fuzzy
+msgid ""
+"The Image Location field MUST be a valid and direct URL to the image binary. "
+"URLs that redirect or serve error pages will result in unusable images."
+msgstr ""
+"イメージの場所の項目は、イメージバイナリーへの有効かつ直接的な URL である必要"
+"があります。リダイレクトや処理エラーページの URL ならば、イメージが利用不可能"
+"になります。"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:3
+msgid "Image Overview"
+msgstr "イメージの概要"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:6
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:7
+#: dashboards/project/instances/templates/instances/_detail_overview.html:6
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:6
+msgid "Info"
+msgstr "情報"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:17
+msgid "Checksum"
+msgstr "チェックサム"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:19
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:39
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:28
+msgid "Created"
+msgstr "作成日時"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:21
+msgid "Updated"
+msgstr "更新日時"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:27
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:34
+#: dashboards/project/instances/templates/instances/_detail_overview.html:19
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:23
+msgid "Specs"
+msgstr "スペック"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:32
+msgid "Container Format"
+msgstr "格納形式"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:34
+msgid "Disk Format"
+msgstr "ディスク形式"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:40
+msgid "Custom Properties"
+msgstr "カスタム属性"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:56
+msgid "Euca2ools state"
+msgstr "Euca2ools の状態"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:64
+msgid "Image Type"
+msgstr "イメージ種別"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html:4
+msgid "Image Detail "
+msgstr "イメージの詳細"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:8
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:3
+#: dashboards/project/instances/tables.py:179
+#: dashboards/project/volumes/tables.py:76
+msgid "Create Snapshot"
+msgstr "スナップショットの作成"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:18
+msgid "Snapshots preserve the disk state of a running instance."
+msgstr "スナップショットは実行中のインスタンスのディスク状態を保存します。"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:20
+#: dashboards/project/instances/workflows.py:75
+#: dashboards/project/instances/workflows.py:110
+#: dashboards/project/instances/templates/instances/_detail_overview.html:93
+#: dashboards/project/volumes/tables.py:37
+#: dashboards/project/volumes/tables.py:182
+msgid "Volume"
+msgstr "ボリューム"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:38
+#: dashboards/project/instances/templates/instances/_detail_overview.html:29
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:27
+msgid "GB"
+msgstr "GB"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:6
+msgid "Create a Snapshot"
+msgstr "スナップショットの作成"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:3
+#, fuzzy
+msgid "Volume Snapshot Details"
+msgstr "ボリュームスナップショット"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:6
+#, fuzzy
+msgid "Volume Snapshot Detail"
+msgstr "ボリュームスナップショット"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:34
+#: dashboards/project/instances/workflows.py:76
+msgid "Volume Snapshot"
+msgstr "ボリュームスナップショット"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:35
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:85
+msgid "Volume Snapshots"
+msgstr "ボリュームスナップショット"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:43
+#: dashboards/project/volumes/tables.py:59
+#: dashboards/project/volumes/templates/volumes/_create.html:8
+#: dashboards/project/volumes/templates/volumes/_create.html:55
+msgid "Create Volume"
+msgstr "ボリュームの作成"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:80
+#: dashboards/project/volumes/forms.py:26
+msgid "Volume Name"
+msgstr "ボリューム名"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:41
+#, fuzzy
+msgid "Unable to retrieve snapshot details."
+msgstr "ポートの詳細を取得できません。"
+
+#: dashboards/project/instances/forms.py:45
+#, python-format
+msgid "Instance \"%s\" updated."
+msgstr "インスタンス \"%s\" を更新しました。"
+
+#: dashboards/project/instances/forms.py:50
+msgid "Unable to update instance."
+msgstr "インスタンスを更新できません。"
+
+#: dashboards/project/instances/tables.py:67
+msgid "Terminate"
+msgstr "削除"
+
+#: dashboards/project/instances/tables.py:68
+msgid "Scheduled termination of"
+msgstr "スケジュール削除"
+
+#: dashboards/project/instances/tables.py:87
+msgid "Reboot"
+msgstr "再起動します"
+
+#: dashboards/project/instances/tables.py:88
+msgid "Rebooted"
+msgstr "再起動しました"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Pause"
+msgstr "一時停止します"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Unpause"
+msgstr "再開します"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Paused"
+msgstr "一時停止しました"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Unpaused"
+msgstr "再開しました"
+
+#: dashboards/project/instances/tables.py:133
+msgid "Suspend"
+msgstr "休止します"
+
+#: dashboards/project/instances/tables.py:133
+msgid "Resume"
+msgstr "再開します"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Suspended"
+msgstr "休止しました"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Resumed"
+msgstr "再開しました"
+
+#: dashboards/project/instances/tables.py:162
+#: dashboards/project/instances/workflows.py:454
+#: dashboards/project/instances/templates/instances/launch.html:3
+#: dashboards/project/instances/templates/instances/launch.html:6
+msgid "Launch Instance"
+msgstr "イメージの起動"
+
+#: dashboards/project/instances/tables.py:169
+#: dashboards/project/instances/templates/instances/_update.html:7
+msgid "Edit Instance"
+msgstr "インスタンスの編集"
+
+#: dashboards/project/instances/tables.py:189
+msgid "VNC Console"
+msgstr "VNC コンソール"
+
+#: dashboards/project/instances/tables.py:204
+msgid "View Log"
+msgstr "ログの参照"
+
+#: dashboards/project/instances/tables.py:252
+#, python-format
+msgid "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disk"
+msgstr "%(name)s | %(RAM)s メモリー | %(VCPU)s 仮想 CPU | %(disk)s ディスク"
+
+#: dashboards/project/instances/tables.py:259
+#: dashboards/project/instances/tables.py:266
+msgid "Not available"
+msgstr "利用できません"
+
+#: dashboards/project/instances/tabs.py:36
+msgid "Log"
+msgstr "ログ"
+
+#: dashboards/project/instances/tabs.py:48
+#: dashboards/project/instances/views.py:106
+#, python-format
+msgid "Unable to get log for instance \"%s\"."
+msgstr "インスタンス \"%s\" のログを取得できません。"
+
+#: dashboards/project/instances/tabs.py:55
+msgid "VNC"
+msgstr "VNC"
+
+#: dashboards/project/instances/tabs.py:70
+#: dashboards/project/instances/views.py:122
+#, python-format
+msgid "Unable to get VNC console for instance \"%s\"."
+msgstr "インスタンス \"%s\" の VNC コンソールを取得できません。"
+
+#: dashboards/project/instances/views.py:59
+msgid "Unable to retrieve instances."
+msgstr "インスタンスを取得できません。"
+
+#: dashboards/project/instances/views.py:144
+msgid "Unable to retrieve instance details."
+msgstr "インスタンスの詳細を取り出せません。"
+
+#: dashboards/project/instances/views.py:179
+#, python-format
+msgid "Unable to retrieve details for instance \"%s\"."
+msgstr "インスタンス \"%s\" の詳細を取り出せません。"
+
+#: dashboards/project/instances/workflows.py:53
+msgid "Project & User"
+msgstr "プロジェクト使用状況"
+
+#: dashboards/project/instances/workflows.py:66
+msgid "Don't boot from a volume."
+msgstr "ボリュームから起動しません。"
+
+#: dashboards/project/instances/workflows.py:67
+msgid "Boot from volume."
+msgstr "ボリュームから起動します。"
+
+#: dashboards/project/instances/workflows.py:68
+msgid "Boot from volume snapshot (creates a new volume)."
+msgstr ""
+"ボリュームのスナップショットから起動します(新しいボリュームを作成します)。"
+
+#: dashboards/project/instances/workflows.py:72
+#: dashboards/project/instances/workflows.py:90
+msgid "Volume Options"
+msgstr "ボリュームの詳細"
+
+#: dashboards/project/instances/workflows.py:78
+#: dashboards/project/volumes/forms.py:126
+msgid "Device Name"
+msgstr "デバイス名"
+
+#: dashboards/project/instances/workflows.py:81
+msgid "Volume mount point (e.g. 'vda' mounts at '/dev/vda')."
+msgstr ""
+"ボリュームのマウントポイント (例 'vda' と指定すると '/dev/vda' にマウントされ"
+"ます)。"
+
+#: dashboards/project/instances/workflows.py:83
+msgid "Delete on Terminate"
+msgstr "終了時に削除します"
+
+#: dashboards/project/instances/workflows.py:86
+msgid "Delete volume on instance terminate"
+msgstr "インスタンス終了時にボリュームを削除します"
+
+#: dashboards/project/instances/workflows.py:100
+#, python-format
+msgid "Please choose a volume, or select %s."
+msgstr "ボリュームを選択してください、または %s を選択してください。"
+
+#: dashboards/project/instances/workflows.py:117
+msgid "Select Volume"
+msgstr "ボリュームの選択"
+
+#: dashboards/project/instances/workflows.py:125
+msgid "Unable to retrieve list of volumes."
+msgstr "ボリュームの一覧を取得できません。"
+
+#: dashboards/project/instances/workflows.py:129
+msgid "Select Volume Snapshot"
+msgstr "ボリュームオプション"
+
+#: dashboards/project/instances/workflows.py:138
+msgid "Unable to retrieve list of volume snapshots."
+msgstr "ボリュームのスナップショットの一覧を取得できません。"
+
+#: dashboards/project/instances/workflows.py:171
+msgid "Instance Source"
+msgstr "インスタンス・ソース"
+
+#: dashboards/project/instances/workflows.py:174
+msgid "Instance Snapshot"
+msgstr "インスタンスのスナップショット"
+
+#: dashboards/project/instances/workflows.py:178
+msgid "Size of image to launch."
+msgstr "起動するイメージの容量。"
+
+#: dashboards/project/instances/workflows.py:179
+msgid "Instance Count"
+msgstr "インスタンス数"
+
+#: dashboards/project/instances/workflows.py:182
+msgid "Number of instances to launch."
+msgstr "起動するインスタンス数。"
+
+#: dashboards/project/instances/workflows.py:185
+msgid "Details"
+msgstr "詳細"
+
+#: dashboards/project/instances/workflows.py:198
+msgid ""
+"There are no image sources available; you must first create an image before "
+"attempting to launch an instance."
+msgstr ""
+"利用可能なイメージソースがありません。インスタンスを起動しようとする前に、ま"
+"ずイメージを作成する必要があります。"
+
+#: dashboards/project/instances/workflows.py:203
+msgid "Please select an option for the instance source."
+msgstr "インスタンスソースのオプションを選択してください。"
+
+#: dashboards/project/instances/workflows.py:212
+msgid ""
+"Launching multiple instances is only supported for images and instance "
+"snapshots."
+msgstr ""
+"複数のインスタンスを起動することは、イメージおよびインスタンスのスナップ"
+"ショットに対してのみサポートされます。"
+
+#: dashboards/project/instances/workflows.py:229
+msgid "Unable to retrieve public images."
+msgstr "公開イメージを取得できません。"
+
+#: dashboards/project/instances/workflows.py:244
+msgid "Unable to retrieve images for the current project."
+msgstr "現在のプロジェクト向けのイメージを取得できません。"
+
+#: dashboards/project/instances/workflows.py:267
+msgid "Select Image"
+msgstr "イメージの選択"
+
+#: dashboards/project/instances/workflows.py:269
+msgid "No images available."
+msgstr "利用可能なイメージがありません。"
+
+#: dashboards/project/instances/workflows.py:278
+msgid "Select Instance Snapshot"
+msgstr "インスタンスのスナップショットの選択"
+
+#: dashboards/project/instances/workflows.py:280
+msgid "No snapshots available."
+msgstr "利用可能なスナップショットがありません。"
+
+#: dashboards/project/instances/workflows.py:291
+msgid "Unable to retrieve instance flavors."
+msgstr "インスタンスのタイプを取得できません。"
+
+#: dashboards/project/instances/workflows.py:304 usage/base.py:114
+msgid "Unable to retrieve quota information."
+msgstr "クォータ情報を取得できません。"
+
+#: dashboards/project/instances/workflows.py:337
+msgid "Which keypair to use for authentication."
+msgstr "認証に使用するキーペアを選択してください。"
+
+#: dashboards/project/instances/workflows.py:344
+msgid "Launch instance in these security groups."
+msgstr "これらのセキュリティグループにインスタンスを起動します。"
+
+#: dashboards/project/instances/workflows.py:349
+msgid ""
+"Control access to your instance via keypairs, security groups, and other "
+"mechanisms."
+msgstr ""
+"キーペア、セキュリティグループ、および他のメカニズムを通してインスタンスへの"
+"アクセスを制御します。"
+
+#: dashboards/project/instances/workflows.py:359
+msgid "Unable to retrieve keypairs."
+msgstr "キーペアを取得できません。"
+
+#: dashboards/project/instances/workflows.py:361
+msgid "Select a keypair"
+msgstr "キーペアの選択"
+
+#: dashboards/project/instances/workflows.py:363
+msgid "No keypairs available."
+msgstr "利用可能なキーペアがありません。"
+
+#: dashboards/project/instances/workflows.py:372
+msgid "Unable to retrieve list of security groups"
+msgstr "セキュリティグループの一覧を取得できません"
+
+#: dashboards/project/instances/workflows.py:392
+msgid "Customization Script"
+msgstr "カスタマイズ・スクリプト"
+
+#: dashboards/project/instances/workflows.py:394
+msgid ""
+"A script or set of commands to be executed after the instance has been built "
+"(max 16kb)."
+msgstr ""
+"インスタンスが構築された後に実行されるスクリプトまたは一組のコマンドです(最"
+"大 16 kb)。"
+
+#: dashboards/project/instances/workflows.py:401
+msgid "Post-Creation"
+msgstr "作成後"
+
+#: dashboards/project/instances/workflows.py:415
+msgid "Launch instance withthese networks"
+msgstr "これらのネットワークとともにインスタンスを起動します"
+
+#: dashboards/project/instances/workflows.py:419
+msgid "Networking"
+msgstr "ネットワーク"
+
+#: dashboards/project/instances/workflows.py:421
+msgid "Select networks for your instance."
+msgstr "インスタンスのネットワークを選択します。"
+
+#: dashboards/project/instances/workflows.py:433
+msgid "Unable to retrieve networks."
+msgstr "ネットワークを取得できません。"
+
+#: dashboards/project/instances/workflows.py:456
+#, python-format
+msgid "Launched %(count)s named \"%(name)s\"."
+msgstr "%(count)s 個の \"%(name)s\" を起動しました。"
+
+#: dashboards/project/instances/workflows.py:457
+#, python-format
+msgid "Unable to launch %(count)s named \"%(name)s\"."
+msgstr "%(count)s 個の \"%(name)s\" を起動できません。"
+
+#: dashboards/project/instances/workflows.py:470
+#, python-format
+msgid "%s instances"
+msgstr "%s インスタンス"
+
+#: dashboards/project/instances/workflows.py:473
+msgid "instance"
+msgstr "インスタンス"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:4
+msgid "Instance Console Log"
+msgstr "インスタンスのコンソールログ"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:7
+msgid "Log Length"
+msgstr "ログ長"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:9
+msgid "Go"
+msgstr "Go"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:11
+msgid "View Full Log"
+msgstr "全てのログの表示"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:3
+msgid "Instance Overview"
+msgstr "インスタンスの概要"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:27
+msgid "VCPU"
+msgstr "仮想 CPU"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:28
+#: usage/tables.py:20
+msgid "Disk"
+msgstr "ディスク"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:34
+msgid "IP Addresses"
+msgstr "IP アドレス"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:59
+msgid "No rules defined."
+msgstr "ルールが定義されていません。"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:68
+msgid "Meta"
+msgstr "メタ情報"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:71
+msgid "Key Name"
+msgstr "キーペア名"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:84
+msgid "Volumes Attached"
+msgstr "接続されているボリューム"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:88
+#: dashboards/project/volumes/tables.py:167
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:38
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:45
+msgid "Attached To"
+msgstr "接続先"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:90
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:42
+msgid "on"
+msgstr "の"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:94
+msgid "No volumes attached."
+msgstr "ボリュームが接続されていません。"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:3
+msgid "Instance VNC Console"
+msgstr "インスタンスの VNC コンソール"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid ""
+"If VNC console is not responding to keyboard input: click the grey status "
+"bar below."
+msgstr ""
+"VNC コンソールがキーボード入力に対応していなければ、以下のグレーのステータス"
+"バーをクリックしてください。"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid "Click here to show only VNC"
+msgstr "VNC のみを表示するにはここをクリックします"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:8
+msgid "VNC console is currently unavailabe. Please try again later."
+msgstr "VNC コンソールが現在利用できません。後から再びお試しください。"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:9
+msgid "Reload"
+msgstr "リロード"
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:2
+msgid ""
+"You can customize your instance after it's launched using the options "
+"available here."
+msgstr ""
+"ここで利用可能なオプションを使用して起動した後でインスタンスをカスタマイズで"
+"きます。"
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:3
+msgid ""
+"The \"Customization Script\" field is analogous to \"User Data\" in other "
+"systems."
+msgstr ""
+"\"カスタマイズ・スクリプト\" 項目は他のシステムにおける \"ユーザーデータ\" と"
+"類似しています。"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:3
+msgid "Specify the details for launching an instance."
+msgstr "インスタンスを起動するために詳細を指定します。"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:4
+msgid ""
+"The chart below shows the resources used by this project in relation to the "
+"project's quotas."
+msgstr ""
+"以下の図は、このプロジェクトにより使用されているリソースを、プロジェクトの"
+"クォータと関連付けて表示します。"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:6
+msgid "Flavor Details"
+msgstr "インタスタンスタイプの詳細"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+msgid "Total Disk"
+msgstr "合計ディスク"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "MB"
+msgstr "MB"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:21
+msgid "Number of Instances"
+msgstr "インスタンス数"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:29
+msgid "Number of VCPUs"
+msgstr "仮想 CPU 数"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+#, fuzzy
+msgid "Total RAM"
+msgstr "合計メモリー"
+
+#: dashboards/project/instances/templates/instances/_launch_volumes_help.html:3
+msgid ""
+"An instance can be launched with varying types of attached storage. You may "
+"select from those options here."
+msgstr ""
+"インスタンスはさまざまな形式のストレージを接続して起動できます。ここからこれ"
+"らのオプションを選択できます。"
+
+#: dashboards/project/instances/templates/instances/_update.html:17
+msgid "You may update the editable properties of your instance here."
+msgstr "ここからインスタンスの編集可能なプロパティーを更新できます。"
+
+#: dashboards/project/instances/templates/instances/detail.html:3
+msgid "Instance Detail"
+msgstr "インスタンスの詳細"
+
+#: dashboards/project/instances/templates/instances/update.html:3
+#: dashboards/project/instances/templates/instances/update.html:6
+msgid "Update Instance"
+msgstr "インスタンスの更新"
+
+#: dashboards/project/networks/tables.py:81
+msgid "Add Subnet"
+msgstr "サブネットの追加"
+
+#: dashboards/project/networks/views.py:86
+msgid "Unable to retrieve network details."
+msgstr "ネットワークの詳細を取得できません。"
+
+#: dashboards/project/networks/workflows.py:37
+msgid "Network Name (optional)"
+msgstr "ネットワーク名 (オプション)"
+
+#: dashboards/project/networks/workflows.py:42
+msgid ""
+"From here you can create a new network.\n"
+"In addition a subnet associated with the network can be created in the next "
+"panel."
+msgstr ""
+"新しいネットワークを作成できます。\n"
+"合わせて、このネットワークに割り当てられたサブネットを次のパネルにおいて作成"
+"できます。"
+
+#: dashboards/project/networks/workflows.py:56
+msgid "Subnet Name (optional)"
+msgstr "サブネット名 (オプション)"
+
+#: dashboards/project/networks/workflows.py:61
+#: dashboards/project/networks/subnets/forms.py:48
+msgid "Network address in CIDR format (e.g. 192.168.0.0/24)"
+msgstr "CIDR 形式のネットワークアドレス (例: 192.168.0.0/24)"
+
+#: dashboards/project/networks/workflows.py:67
+msgid "Gateway IP (optional)"
+msgstr "ゲートウェイ IP (オプション)"
+
+#: dashboards/project/networks/workflows.py:70
+#: dashboards/project/networks/subnets/forms.py:57
+#: dashboards/project/networks/subnets/forms.py:107
+msgid "IP address of Gateway (e.g. 192.168.0.1)"
+msgstr "ゲートウェイの IP アドレス (例: 192.168.0.1)"
+
+#: dashboards/project/networks/workflows.py:77
+msgid ""
+"You can create a subnet associated with the new network, in which case "
+"\"Network Address\" must be specified. If you wish to create a network "
+"WITHOUT a subnet, uncheck the \"Create Subnet\" checkbox."
+msgstr ""
+"新しいネットワークに関連付けるサブネットを作成できます。この場合、「ネット"
+"ワークアドレス」を指定する必要があります。サブネットなしでネットワークを作成"
+"したければ、「サブネットの作成」チェックボックスをチェック解除します。"
+
+#: dashboards/project/networks/workflows.py:89
+msgid "Specify \"Network Address\" or clear \"Create Subnet\" checkbox."
+msgstr ""
+"\"ネットワークアドレス\" を指定してください、または \"サブネットの作成\" "
+"チェックボックスを解除してください。"
+
+#: dashboards/project/networks/workflows.py:94
+#: dashboards/project/networks/subnets/forms.py:70
+msgid "Network Address and IP version are inconsistent."
+msgstr "ネットワークアドレスと IP バージョンが一致していません。"
+
+#: dashboards/project/networks/workflows.py:98
+#: dashboards/project/networks/subnets/forms.py:74
+#: dashboards/project/networks/subnets/forms.py:119
+msgid "Gateway IP and IP version are inconsistent."
+msgstr "ゲートウェイの IP アドレスと IP バージョンが一致していません。"
+
+#: dashboards/project/networks/workflows.py:112
+msgid "Create"
+msgstr "作成"
+
+#: dashboards/project/networks/workflows.py:113
+#, python-format
+msgid "Created network \"%s\"."
+msgstr "ネットワーク \"%s\" を作成しました。"
+
+#: dashboards/project/networks/workflows.py:114
+#, python-format
+msgid "Unable to create network \"%s\"."
+msgstr "ネットワーク \"%s\" の作成に失敗しました。"
+
+#: dashboards/project/networks/workflows.py:130
+#, python-format
+msgid "Network \"%s\" was successfully created."
+msgstr "ネットワーク \"%s\" が正常に作成されました。"
+
+#: dashboards/project/networks/workflows.py:133
+#, python-format
+msgid "Failed to create network \"%s\"."
+msgstr "ネットワーク \"%s\" の作成に失敗しました。"
+
+#: dashboards/project/networks/workflows.py:152
+#, python-format
+msgid "Subnet \"%s\" was successfully created."
+msgstr "サブネット \"%s\" が正常に作成されました。"
+
+#: dashboards/project/networks/workflows.py:155
+#, python-format
+msgid "Failed to create subnet \"%(sub)s\" for network \"%(net)s\"."
+msgstr ""
+"ネットワーク \"%(net)s\" のサブネット \"%(sub)s\" の作成に失敗しました。"
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Attached"
+msgstr "接続しました"
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Detached"
+msgstr "切断しました"
+
+#: dashboards/project/networks/subnets/forms.py:85
+#, python-format
+msgid "Subnet %s was successfully created."
+msgstr "サブネット %s が正常に作成されました。"
+
+#: dashboards/project/networks/subnets/forms.py:90
+#, python-format
+msgid "Failed to create subnet %s"
+msgstr "サブネット %s の作成に失敗しました"
+
+#: dashboards/project/networks/subnets/forms.py:131
+#, python-format
+msgid "Subnet %s was successfully updated."
+msgstr "サブネット %s が正常に更新されました。"
+
+#: dashboards/project/networks/subnets/forms.py:136
+#, python-format
+msgid "Failed to update subnet %s"
+msgstr "サブネット %s の更新に失敗しました"
+
+#: dashboards/project/networks/subnets/tabs.py:42
+msgid "Unable to retrieve subnet details."
+msgstr "サブネットの詳細を取得できません。"
+
+#: dashboards/project/networks/templates/networks/_detail_overview.html:3
+msgid "Network Overview"
+msgstr "ネットワークの概要"
+
+#: dashboards/project/networks/templates/networks/detail.html:6
+msgid "Network Detail: "
+msgstr "ネットワークの詳細: "
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:3
+msgid "Port Overview"
+msgstr "ポートの概要"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:17
+msgid "Fixed IP"
+msgstr "固定 IP"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:21
+msgid "IP address:"
+msgstr "IP アドレス:"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:22
+msgid "Subnet ID"
+msgstr "サブネット ID"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:28
+msgid "Mac Address"
+msgstr "MAC アドレス"
+
+#: dashboards/project/networks/templates/networks/ports/detail.html:3
+#: dashboards/project/networks/templates/networks/ports/detail.html:6
+msgid "Port Detail"
+msgstr "ポートの詳細"
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:3
+msgid "Subnet Overview"
+msgstr "サブネットの概要"
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:21
+msgid "IP allocation pool"
+msgstr "IP 割り当てプール"
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:24
+msgid "Start"
+msgstr "開始"
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:25
+msgid " - End"
+msgstr " - 終了"
+
+#: dashboards/project/networks/templates/networks/subnets/detail.html:3
+#: dashboards/project/networks/templates/networks/subnets/detail.html:6
+msgid "Subnet Detail"
+msgstr "サブネットの詳細"
+
+#: dashboards/project/volumes/forms.py:29
+msgid "Size (GB)"
+msgstr "容量 (GB)"
+
+#: dashboards/project/volumes/forms.py:30
+msgid "Use snapshot as a source"
+msgstr "ソースとしてスナップショットの使用"
+
+#: dashboards/project/volumes/forms.py:49
+#, python-format
+msgid "Volume size must be equal to or greater than the snapshot size (%sGB)"
+msgstr ""
+"ボリューム容量はスナップショット容量 (%sGB) と同じか大きくなければいけませ"
+"ん。"
+
+#: dashboards/project/volumes/forms.py:54
+msgid "Unable to load the specified snapshot."
+msgstr "指定されたスナップショットを読み込めません。"
+
+#: dashboards/project/volumes/forms.py:59
+msgid "Choose a snapshot"
+msgstr "スナップショットの選択"
+
+#: dashboards/project/volumes/forms.py:83
+#, python-format
+msgid "The volume size cannot be less than the snapshot size (%sGB)"
+msgstr "ボリューム容量はスナップショット容量 (%sGB) より小さくできません。"
+
+#: dashboards/project/volumes/forms.py:92
+#, python-format
+msgid ""
+"A volume of %(req)iGB cannot be created as you only have %(avail)iGB of your "
+"quota available."
+msgstr ""
+"利用可能なクォータは %(avail)iGB しかないため、%(req)iGB のボリュームは作成で"
+"きません。"
+
+#: dashboards/project/volumes/forms.py:99
+msgid "You are already using all of your available volumes."
+msgstr "すでに利用可能なすべてのボリュームを使用しています。"
+
+#: dashboards/project/volumes/forms.py:115
+msgid "Unable to create volume."
+msgstr "ボリュームを作成できません。"
+
+#: dashboards/project/volumes/forms.py:123
+msgid "Attach to Instance"
+msgstr "インスタンスへの接続"
+
+#: dashboards/project/volumes/forms.py:124
+msgid "Select an instance to attach to."
+msgstr "接続するインスタンスを選択してください。"
+
+#: dashboards/project/volumes/forms.py:168
+msgid "Unknown instance (None)"
+msgstr "未知のインスタンス (None)"
+
+#: dashboards/project/volumes/forms.py:179
+#, python-format
+msgid "Attaching volume %(vol)s to instance %(inst)s on %(dev)s."
+msgstr ""
+"ボリューム %(vol)s をインスタンス %(inst)s の %(dev)s に接続しています。"
+
+#: dashboards/project/volumes/forms.py:188
+msgid "Unable to attach volume."
+msgstr "ボリュームを接続できません。"
+
+#: dashboards/project/volumes/forms.py:212
+#, python-format
+msgid "Creating volume snapshot \"%s\""
+msgstr "ボリュームのスナップショット \"%s\" を作成しています"
+
+#: dashboards/project/volumes/forms.py:218
+msgid "Unable to create volume snapshot."
+msgstr "ボリュームのスナップショットを作成できません。"
+
+#: dashboards/project/volumes/tables.py:46
+#, fuzzy, python-format
+msgid "Unable to delete volume \"%s\". One or more snapshots depend on it."
+msgstr "ボリュームのスナップショット情報を取得できません。"
+
+#: dashboards/project/volumes/tables.py:66
+msgid "Edit Attachments"
+msgstr "接続の編集"
+
+#: dashboards/project/volumes/tables.py:93
+#, python-format
+msgid "%sGB"
+msgstr "%sGB"
+
+#: dashboards/project/volumes/tables.py:106
+#: dashboards/project/volumes/views.py:149
+msgid "Unable to retrieve attachment information."
+msgstr "接続情報を取得できません。"
+
+#: dashboards/project/volumes/tables.py:123
+#, python-format
+msgid "Attached to %(instance)s on %(dev)s"
+msgstr "%(instance)s の %(dev)s に接続しました"
+
+#: dashboards/project/volumes/tables.py:180
+msgid "Detach"
+msgstr "切断します"
+
+#: dashboards/project/volumes/tables.py:181
+msgid "Detaching"
+msgstr "切断中"
+
+#: dashboards/project/volumes/tables.py:216
+#, python-format
+msgid "%(dev)s on instance %(instance_name)s"
+msgstr "インスタンス %(instance_name)s 上の %(dev)s"
+
+#: dashboards/project/volumes/tabs.py:42
+msgid "Unable to retrieve volume details."
+msgstr "ボリュームの詳細を取得できません。"
+
+#: dashboards/project/volumes/views.py:50
+msgid "Unable to retrieve volume list."
+msgstr "ボリューム一覧を取得できません。"
+
+#: dashboards/project/volumes/views.py:58
+msgid "Unable to retrieve volume/instance attachment information"
+msgstr "ボリューム / インスタンスの接続情報を取得できません"
+
+#: dashboards/project/volumes/views.py:130
+#: dashboards/project/volumes/views.py:140
+msgid "Unable to retrieve volume information."
+msgstr "ボリューム情報を取得できません。"
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:9
+#: dashboards/project/volumes/templates/volumes/attach.html:6
+msgid "Manage Volume Attachments"
+msgstr "ボリュームの接続の管理"
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:13
+msgid "Attach To Instance"
+msgstr "インスタンスへの接続"
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:22
+msgid "Attach Volume"
+msgstr "ボリュームの接続"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:20
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:18
+msgid "Volumes are block devices that can be attached to instances."
+msgstr "ボリュームは、インスタンスに接続できるブロックデバイスです。"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:22
+msgid "Volume Quotas"
+msgstr "ボリュームのクォータ"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:25
+msgid "Total Gigabytes"
+msgstr "合計ギガバイト"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:34
+msgid "Number of Volumes"
+msgstr "ボリューム数"
+
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:8
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:23
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:3
+msgid "Create Volume Snapshot"
+msgstr "ボリュームのスナップショットの作成"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:3
+msgid "Volume Overview"
+msgstr "ボリュームの概要"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:34
+msgid "Attachments"
+msgstr "接続状況"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:46
+msgid "Not attached"
+msgstr "未接続"
+
+#: dashboards/project/volumes/templates/volumes/create.html:6
+msgid "Create a Volume"
+msgstr "ボリュームの作成"
+
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:6
+msgid "Create a Volume Snapshot"
+msgstr "ボリュームのスナップショットの作成"
+
+#: dashboards/settings/dashboard.py:24 templates/_header.html:4
+msgid "Settings"
+msgstr "設定"
+
+#: dashboards/settings/ec2/forms.py:36 dashboards/settings/project/forms.py:36
+msgid "Select a Project"
+msgstr "プロジェクトを選択して下さい"
+
+#: dashboards/settings/ec2/forms.py:46
+msgid "Unable to retrieve tenant list."
+msgstr "プロジェクトリストを取得できません。"
+
+#: dashboards/settings/ec2/forms.py:88
+msgid "Unable to fetch EC2 credentials."
+msgstr "EC2 認証情報を取得できません。"
+
+#: dashboards/settings/ec2/forms.py:101
+#, python-format
+msgid "Error writing zipfile: %(exc)s"
+msgstr "zip ファイル %(exc)s の書き込みに失敗しました。"
+
+#: dashboards/settings/ec2/panel.py:25
+msgid "EC2 Credentials"
+msgstr "EC2 認証情報"
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:8
+#: dashboards/settings/ec2/templates/ec2/download_form.html:23
+#: dashboards/settings/ec2/templates/ec2/index.html:3
+#: dashboards/settings/ec2/templates/ec2/index.html:6
+msgid "Download EC2 Credentials"
+msgstr "EC2 認証情報のダウンロード"
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:18
+msgid ""
+"Clicking \"Download EC2 Credentials\" will download a zip file which "
+"includes an rc file with your access/secret keys, as well as your x509 "
+"private key and certificate."
+msgstr ""
+"\"EC2 認証情報のダウンロード\" をクリックすることにより、アクセスキー・シーク"
+"レットキーを持つ rc ファイル、x509 プライベートキーおよび証明書を含む zip "
+"ファイルをダウンロードします。"
+
+#: dashboards/settings/project/forms.py:71
+#, python-format
+msgid "Error Downloading RC File: %s"
+msgstr "RC ファイル %s のダウンロードに失敗しました。"
+
+#: dashboards/settings/project/panel.py:25
+#: dashboards/settings/project/templates/project/_openrc.html:8
+#: dashboards/settings/project/templates/project/settings.html:3
+#: dashboards/settings/project/templates/project/settings.html:6
+msgid "OpenStack API"
+msgstr "OpenStack API"
+
+#: dashboards/settings/project/tables.py:27
+msgid "Service Name"
+msgstr "サービス名"
+
+#: dashboards/settings/project/tables.py:29
+msgid "Service Endpoint"
+msgstr "サービス・エンドポイント"
+
+#: dashboards/settings/project/tables.py:33
+msgid "API Endpoints"
+msgstr "API エンドポイント"
+
+#: dashboards/settings/project/templates/project/_openrc.html:15
+msgid "Download OpenStack RC File"
+msgstr "OpenStack RC ファイルのダウンロード"
+
+#: dashboards/settings/project/templates/project/_openrc.html:25
+msgid ""
+"Download the RC file for the selected project, then type \"source openrc\" "
+"in the terminal to configure your environment to communicate with OpenStack."
+msgstr ""
+"OpenStack と通信するよう環境を設定するには、選択したプロジェクトに対する RC "
+"ファイルをダウンロードします。そして、ターミナルにおいて \"source openrc\" と"
+"入力します。"
+
+#: dashboards/settings/project/templates/project/_openrc.html:30
+msgid "Download RC File"
+msgstr "RC ファイルのダウンロード"
+
+#: dashboards/settings/user/forms.py:57
+msgid "Settings saved."
+msgstr "設定を保存しました。"
+
+#: dashboards/settings/user/panel.py:25
+#: dashboards/settings/user/templates/user/_settings.html:8
+#: dashboards/settings/user/templates/user/settings.html:3
+#: dashboards/settings/user/templates/user/settings.html:6
+msgid "User Settings"
+msgstr "ユーザーの設定"
+
+#: dashboards/settings/user/templates/user/_settings.html:18
+msgid "From here you can modify dashboard settings for your user."
+msgstr "ここからユーザー向けダッシュボードの設定を変更できます。"
+
#: templates/403.html:4 templates/403.html.py:9
msgid "Forbidden"
msgstr "権限がありません"
@@ -84,10 +3329,6 @@ msgstr "権限がありません"
msgid "Home"
msgstr "ホーム"
-#: templates/403.html:24 templates/404.html:23 templates/500.html:23
-msgid "Projects"
-msgstr "プロジェクト"
-
#: templates/404.html:4
msgid "Page Not Found"
msgstr "ページが見つかりませんでした"
@@ -111,3 +3352,47 @@ msgid ""
msgstr ""
"リクエストの処理中に予期しないエラーが発生しました。再びリクエストを試行して"
"ください。"
+
+#: templates/_header.html:3
+msgid "Logged in as"
+msgstr "次の役割でログインしました"
+
+#: templates/_header.html:6
+msgid "Help"
+msgstr "ヘルプ"
+
+#: templates/_header.html:8
+msgid "Sign Out"
+msgstr "ログアウト"
+
+#: test/settings.py:50
+msgid "Password must be between 8 and 18 characters."
+msgstr "パスワードは 8 から 18 文字である必要があります。"
+
+#: usage/base.py:97
+msgid "Unable to retrieve usage information."
+msgstr "使用情報を取得できません。"
+
+#: usage/base.py:100
+msgid "You are viewing data for the future, which may or may not exist."
+msgstr "結果が反映されるまで時間がかかります。しばらくお待ち下さい。"
+
+#: usage/tables.py:11
+msgid "Download CSV Summary"
+msgstr "CSV ダウンロード"
+
+#: usage/tables.py:25
+msgid "VCPU Hours"
+msgstr "仮想 CPU 時間"
+
+#: usage/tables.py:32
+msgid "Disk GB Hours"
+msgstr "ディスク GB × 時間"
+
+#: usage/tables.py:40 usage/tables.py:68
+msgid "Usage Summary"
+msgstr "使用状況"
+
+#: usage/tables.py:60
+msgid "Uptime"
+msgstr "起動時間"
diff --git a/openstack_dashboard/locale/ko_KR/LC_MESSAGES/django.mo b/openstack_dashboard/locale/ko_KR/LC_MESSAGES/django.mo
index 44c4f1142..6793a2bb1 100644
--- a/openstack_dashboard/locale/ko_KR/LC_MESSAGES/django.mo
+++ b/openstack_dashboard/locale/ko_KR/LC_MESSAGES/django.mo
Binary files differ
diff --git a/openstack_dashboard/locale/ko_KR/LC_MESSAGES/django.po b/openstack_dashboard/locale/ko_KR/LC_MESSAGES/django.po
index 7857624dc..c5ff95e86 100644
--- a/openstack_dashboard/locale/ko_KR/LC_MESSAGES/django.po
+++ b/openstack_dashboard/locale/ko_KR/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Horizon\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-09-18 22:18+0000\n"
+"POT-Creation-Date: 2012-10-05 19:30+0000\n"
"PO-Revision-Date: 2012-08-23 05:30+0000\n"
"Last-Translator: bluejay.kr <bluejay.ahn@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,63 +18,3211 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-#: settings.py:141
+#: settings.py:142
msgid "Bulgarian (Bulgaria)"
msgstr ""
-#: settings.py:142
+#: settings.py:143
msgid "Czech"
msgstr ""
-#: settings.py:143
+#: settings.py:144
msgid "English"
msgstr "영어"
-#: settings.py:144
+#: settings.py:145
msgid "Spanish"
msgstr "스페인어"
-#: settings.py:145
+#: settings.py:146
msgid "French"
msgstr "불어"
-#: settings.py:146
+#: settings.py:147
msgid "Italiano"
msgstr "이탈리아어"
-#: settings.py:147
+#: settings.py:148
msgid "Japanese"
msgstr "일본어"
-#: settings.py:148
+#: settings.py:149
msgid "Korean (Korea)"
msgstr ""
-#: settings.py:149
+#: settings.py:150
msgid "Dutch (Netherlands)"
msgstr ""
-#: settings.py:150
+#: settings.py:151
msgid "Polish"
msgstr "폴란드어어"
-#: settings.py:151
+#: settings.py:152
msgid "Portuguese"
msgstr "포르투갈어"
-#: settings.py:152
+#: settings.py:153
#, fuzzy
msgid "Portuguese (Brazil)"
msgstr "포르투갈어"
-#: settings.py:153
+#: settings.py:154
msgid "Simplified Chinese"
msgstr "중국어-간체"
-#: settings.py:154
+#: settings.py:155
msgid "Traditional Chinese"
msgstr "중국어-정체"
+#: api/keystone.py:56
+#, python-format
+msgid "%(type)s (%(backend)s backend)"
+msgstr ""
+
+#: api/nova.py:191
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(group)s"
+msgstr ""
+
+#: api/nova.py:196
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(cidr)s"
+msgstr ""
+
+#: api/nova.py:532
+msgid "Unknown instance"
+msgstr ""
+
+#: api/swift.py:217
+msgid "Unicode is not currently supported for object copy."
+msgstr ""
+
+#: dashboards/admin/dashboard.py:24
+msgid "System Panel"
+msgstr ""
+
+#: dashboards/admin/dashboard.py:30
+msgid "Admin"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:36 dashboards/admin/networks/forms.py:34
+#: dashboards/admin/networks/forms.py:69
+#: dashboards/admin/networks/ports/forms.py:40
+#: dashboards/admin/networks/ports/forms.py:72
+#: dashboards/admin/networks/ports/tables.py:73
+#: dashboards/admin/networks/subnets/tables.py:70
+#: dashboards/admin/projects/tables.py:87
+#: dashboards/admin/projects/workflows.py:71
+#: dashboards/admin/services/tables.py:38
+#: dashboards/admin/volumes/tables.py:10
+#: dashboards/project/access_and_security/security_groups/forms.py:36
+#: dashboards/project/access_and_security/security_groups/tables.py:58
+#: dashboards/project/images_and_snapshots/images/forms.py:40
+#: dashboards/project/images_and_snapshots/images/forms.py:115
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:9
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:10
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:77
+#: dashboards/project/instances/templates/instances/_detail_overview.html:9
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:9
+#: dashboards/project/networks/forms.py:37
+#: dashboards/project/networks/tables.py:94
+#: dashboards/project/networks/ports/tables.py:40
+#: dashboards/project/networks/subnets/forms.py:43
+#: dashboards/project/networks/subnets/forms.py:102
+#: dashboards/project/networks/subnets/tables.py:82
+#: dashboards/project/networks/templates/networks/_detail_overview.html:7
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:9
+#: dashboards/project/volumes/tables.py:144
+#: dashboards/project/volumes/tables.py:164
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:9
+msgid "Name"
+msgstr "이름"
+
+#: dashboards/admin/flavors/forms.py:37 dashboards/admin/flavors/tables.py:41
+#: dashboards/admin/projects/workflows.py:39
+#: dashboards/project/instances/templates/instances/_detail_overview.html:26
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:10
+#: usage/tables.py:19
+msgid "VCPUs"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:38
+msgid "RAM MB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:39
+msgid "Root Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:40
+msgid "Ephemeral Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:50
+msgid "Unable to get unique ID for new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:67
+#, python-format
+msgid "Created flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:71
+msgid "Unable to create flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:92
+#, python-format
+msgid "Updated flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:96
+msgid "Unable to update flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/panel.py:29 dashboards/admin/flavors/tables.py:15
+#: dashboards/admin/flavors/tables.py:52
+#: dashboards/admin/flavors/templates/flavors/index.html:3
+#: dashboards/admin/flavors/templates/flavors/index.html:6
+msgid "Flavors"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:14
+#: dashboards/project/instances/workflows.py:177
+#: dashboards/project/instances/templates/instances/_detail_overview.html:22
+msgid "Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:23
+#: dashboards/admin/flavors/templates/flavors/_create.html:8
+#: dashboards/admin/flavors/templates/flavors/_create.html:23
+#: dashboards/admin/flavors/templates/flavors/create.html:3
+#: dashboards/admin/flavors/templates/flavors/create.html:6
+msgid "Create Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:30
+#: dashboards/admin/flavors/templates/flavors/_edit.html:8
+#: dashboards/admin/flavors/templates/flavors/edit.html:3
+#: dashboards/admin/flavors/templates/flavors/edit.html:6
+msgid "Edit Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:36
+#, python-format
+msgid "%sMB"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:40
+msgid "Flavor Name"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:43
+#: dashboards/project/instances/templates/instances/_detail_overview.html:24
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: usage/tables.py:22
+msgid "RAM"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:45
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+msgid "Root Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:47
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+msgid "Ephemeral Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:49
+msgid "Unable to retrieve flavor list."
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:76
+msgid "Unable to retrieve flavor data."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:17
+#: dashboards/admin/flavors/templates/flavors/_edit.html:17
+#: dashboards/admin/images/templates/images/_update.html:17
+#: dashboards/admin/networks/templates/networks/_create.html:17
+#: dashboards/admin/networks/templates/networks/ports/_create.html:17
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:17
+#: dashboards/admin/projects/tables.py:89
+#: dashboards/admin/projects/workflows.py:74
+#: dashboards/admin/projects/templates/projects/_add_user.html:17
+#: dashboards/admin/projects/templates/projects/_create.html:17
+#: dashboards/admin/projects/templates/projects/_create_user.html:17
+#: dashboards/admin/projects/templates/projects/_quotas.html:16
+#: dashboards/admin/projects/templates/projects/_update.html:17
+#: dashboards/admin/users/templates/users/_create.html:16
+#: dashboards/admin/users/templates/users/_update.html:16
+#: dashboards/project/access_and_security/security_groups/forms.py:38
+#: dashboards/project/access_and_security/security_groups/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:17
+#: dashboards/project/containers/templates/containers/_copy.html:16
+#: dashboards/project/containers/templates/containers/_create.html:16
+#: dashboards/project/containers/templates/containers/_upload.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/_create.html:16
+#: dashboards/project/networks/templates/networks/subnets/_create.html:17
+#: dashboards/project/volumes/forms.py:28
+#: dashboards/project/volumes/forms.py:195
+#: dashboards/project/volumes/tables.py:147
+#: dashboards/project/volumes/templates/volumes/_create.html:18
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:17
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:14
+msgid "Description"
+msgstr "설명"
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:18
+msgid "From here you can define the sizing of a new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:24
+#: dashboards/admin/flavors/templates/flavors/_edit.html:25
+#: dashboards/admin/images/templates/images/_update.html:24
+#: dashboards/admin/networks/templates/networks/_create.html:24
+#: dashboards/admin/networks/templates/networks/_update.html:23
+#: dashboards/admin/networks/templates/networks/ports/_create.html:24
+#: dashboards/admin/networks/templates/networks/ports/_update.html:28
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:24
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:32
+#: dashboards/admin/projects/templates/projects/_add_user.html:24
+#: dashboards/admin/projects/templates/projects/_create.html:24
+#: dashboards/admin/projects/templates/projects/_create_user.html:24
+#: dashboards/admin/projects/templates/projects/_quotas.html:23
+#: dashboards/admin/projects/templates/projects/_update.html:24
+#: dashboards/admin/users/templates/users/_create.html:23
+#: dashboards/admin/users/templates/users/_update.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:32
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:20
+#: dashboards/project/containers/templates/containers/_copy.html:23
+#: dashboards/project/containers/templates/containers/_create.html:23
+#: dashboards/project/containers/templates/containers/_upload.html:24
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:32
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:24
+#: dashboards/project/instances/templates/instances/_update.html:23
+#: dashboards/project/networks/templates/networks/_create.html:23
+#: dashboards/project/networks/templates/networks/_update.html:23
+#: dashboards/project/networks/templates/networks/subnets/_create.html:24
+#: dashboards/project/networks/templates/networks/subnets/_update.html:32
+#: dashboards/project/volumes/templates/volumes/_attach.html:24
+#: dashboards/project/volumes/templates/volumes/_create.html:56
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:24
+#: dashboards/settings/ec2/templates/ec2/download_form.html:24
+#: dashboards/settings/project/templates/project/_openrc.html:31
+#: dashboards/settings/user/templates/user/_settings.html:24
+msgid "Cancel"
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:18
+msgid "From here you can alter the sizing of the current flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:19
+msgid ""
+"Note: this will not affect the resources allocated to any existing instances "
+"using this flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:24
+#: dashboards/admin/projects/workflows.py:270
+#: dashboards/settings/user/templates/user/_settings.html:23
+msgid "Save"
+msgstr ""
+
+#: dashboards/admin/images/panel.py:29 dashboards/admin/images/tables.py:44
+#: dashboards/admin/images/templates/images/index.html:3
+#: dashboards/admin/images/templates/images/index.html:6
+#: dashboards/project/images_and_snapshots/images/tables.py:47
+#: dashboards/project/images_and_snapshots/images/tables.py:132
+msgid "Images"
+msgstr ""
+
+#: dashboards/admin/images/tables.py:40
+#: dashboards/project/images_and_snapshots/images/tables.py:113
+#: dashboards/project/instances/templates/instances/_detail_overview.html:74
+msgid "Image Name"
+msgstr ""
+
+#: dashboards/admin/images/views.py:55
+msgid "Unable to retrieve image list."
+msgstr ""
+
+#: dashboards/admin/images/templates/images/_update.html:8
+#: dashboards/admin/images/templates/images/_update.html:23
+#: dashboards/admin/images/templates/images/update.html:4
+#: dashboards/admin/images/templates/images/update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:22
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:6
+msgid "Update Image"
+msgstr ""
+
+#: dashboards/admin/images/templates/images/_update.html:18
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:17
+msgid "From here you can modify different properties of an image."
+msgstr ""
+
+#: dashboards/admin/instances/panel.py:29
+#: dashboards/admin/instances/tables.py:94
+#: dashboards/admin/instances/templates/instances/index.html:3
+#: dashboards/admin/projects/workflows.py:40
+#: dashboards/project/instances/panel.py:25
+#: dashboards/project/instances/tables.py:70
+#: dashboards/project/instances/tables.py:90
+#: dashboards/project/instances/tables.py:107
+#: dashboards/project/instances/tables.py:136
+#: dashboards/project/instances/tables.py:313
+#: dashboards/project/instances/templates/instances/index.html:3
+#: dashboards/project/instances/templates/instances/index.html:6
+msgid "Instances"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:60 usage/tables.py:30
+msgid "Project Name"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:67
+#: dashboards/admin/services/tables.py:40
+msgid "Host"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:71
+#: dashboards/project/instances/tables.py:290
+#: dashboards/project/instances/workflows.py:176 usage/tables.py:57
+msgid "Instance Name"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:72
+#: dashboards/project/access_and_security/floating_ips/tables.py:111
+#: dashboards/project/access_and_security/floating_ips/workflows.py:32
+#: dashboards/project/access_and_security/floating_ips/workflows.py:39
+#: dashboards/project/instances/tables.py:291
+msgid "IP Address"
+msgstr "IP어드레스"
+
+#: dashboards/admin/instances/tables.py:74
+#: dashboards/project/containers/tables.py:256
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:30
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:37
+#: dashboards/project/instances/tables.py:293
+#: dashboards/project/volumes/tables.py:150
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:26
+msgid "Size"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:79
+#: dashboards/admin/networks/tables.py:74
+#: dashboards/admin/networks/ports/tables.py:77
+#: dashboards/project/images_and_snapshots/images/tables.py:119
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:13
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:18
+#: dashboards/project/instances/tables.py:298
+#: dashboards/project/instances/templates/instances/_detail_overview.html:13
+#: dashboards/project/networks/tables.py:100
+#: dashboards/project/networks/ports/tables.py:44
+#: dashboards/project/networks/templates/networks/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:30
+#: dashboards/project/volumes/tables.py:154
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:17
+msgid "Status"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:83
+#: dashboards/project/instances/tables.py:302
+msgid "Task"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:90
+#: dashboards/project/instances/tables.py:309
+msgid "Power State"
+msgstr ""
+
+#: dashboards/admin/instances/views.py:49
+#: dashboards/project/access_and_security/views.py:76
+#: dashboards/project/access_and_security/floating_ips/workflows.py:65
+msgid "Unable to retrieve instance list."
+msgstr "인스턴스 목록을 불러올 수 없습니다."
+
+#: dashboards/admin/instances/views.py:63
+#: dashboards/admin/networks/views.py:48
+msgid "Unable to retrieve instance tenant information."
+msgstr ""
+
+#: dashboards/admin/instances/views.py:80
+#: dashboards/project/instances/views.py:82
+msgid "Unable to retrieve instance size information."
+msgstr ""
+
+#: dashboards/admin/instances/templates/instances/index.html:6
+msgid "All Instances"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:36
+#: dashboards/admin/networks/tables.py:67
+#: dashboards/admin/projects/tables.py:65 dashboards/project/dashboard.py:40
+#: dashboards/project/instances/workflows.py:38
+msgid "Project"
+msgstr "프로젝트"
+
+#: dashboards/admin/networks/forms.py:37 dashboards/admin/networks/forms.py:74
+#: dashboards/admin/networks/tables.py:72
+#: dashboards/project/networks/tables.py:98
+#: dashboards/project/networks/templates/networks/_detail_overview.html:17
+msgid "Shared"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:46 dashboards/admin/users/forms.py:42
+msgid "Select a project"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:58
+#, python-format
+msgid "Network %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:64
+#, python-format
+msgid "Failed to create network %s"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:71
+#: dashboards/admin/networks/templates/networks/ports/_update.html:12
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:12
+#: dashboards/admin/users/forms.py:114
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:11
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:12
+#: dashboards/project/instances/templates/instances/_detail_overview.html:11
+#: dashboards/project/networks/forms.py:39
+#: dashboards/project/networks/templates/networks/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_update.html:12
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:11
+msgid "ID"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:82
+#: dashboards/project/networks/forms.py:48
+#, python-format
+msgid "Network %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:87
+#: dashboards/project/networks/forms.py:53
+#, python-format
+msgid "Failed to update network %s"
+msgstr ""
+
+#: dashboards/admin/networks/panel.py:25
+#: dashboards/admin/networks/tables.py:35
+#: dashboards/admin/networks/tables.py:80
+#: dashboards/admin/networks/templates/networks/index.html:3
+#: dashboards/admin/networks/templates/networks/index.html:6
+#: dashboards/project/instances/workflows.py:412
+#: dashboards/project/networks/panel.py:25
+#: dashboards/project/networks/tables.py:44
+#: dashboards/project/networks/tables.py:106
+#: dashboards/project/networks/templates/networks/index.html:3
+#: dashboards/project/networks/templates/networks/index.html:6
+msgid "Networks"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:34
+#: dashboards/project/networks/tables.py:43
+#: dashboards/project/networks/templates/networks/subnets/index.html:3
+#: dashboards/project/networks/templates/networks/subnets/index.html:6
+msgid "Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:41
+#: dashboards/project/networks/tables.py:59
+#, python-format
+msgid "Failed to delete network %s"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:49
+#: dashboards/admin/networks/templates/networks/_create.html:8
+#: dashboards/admin/networks/templates/networks/_create.html:23
+#: dashboards/admin/networks/templates/networks/create.html:3
+#: dashboards/admin/networks/templates/networks/create.html:6
+#: dashboards/project/networks/tables.py:67
+#: dashboards/project/networks/workflows.py:111
+#: dashboards/project/networks/templates/networks/_create.html:7
+#: dashboards/project/networks/templates/networks/_create.html:22
+#: dashboards/project/networks/templates/networks/create.html:3
+#: dashboards/project/networks/templates/networks/create.html:6
+msgid "Create Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:56
+#: dashboards/admin/networks/templates/networks/_update.html:7
+#: dashboards/project/networks/tables.py:74
+#: dashboards/project/networks/templates/networks/_update.html:7
+msgid "Edit Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:68
+#: dashboards/admin/networks/ports/forms.py:33
+#: dashboards/project/networks/subnets/forms.py:35
+msgid "Network Name"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:71
+#: dashboards/project/networks/tables.py:97
+msgid "Subnets Associated"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:76
+#: dashboards/admin/networks/ports/tables.py:79
+#: dashboards/project/networks/tables.py:102
+#: dashboards/project/networks/ports/tables.py:46
+#: dashboards/project/networks/templates/networks/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:32
+msgid "Admin State"
+msgstr ""
+
+#: dashboards/admin/networks/views.py:60
+#: dashboards/project/networks/views.py:52
+msgid "Network list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:91
+#: dashboards/project/networks/views.py:109
+msgid "Subnet list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:103
+#: dashboards/project/networks/views.py:121
+msgid "Port list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:118
+#: dashboards/project/networks/views.py:134
+#: dashboards/project/networks/subnets/tables.py:96
+#, python-format
+msgid "Unable to retrieve details for network \"%s\"."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:36
+#: dashboards/project/networks/subnets/forms.py:39
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:13
+msgid "Network ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:42
+#: dashboards/admin/networks/ports/forms.py:74
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:34
+msgid "Device ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:54
+#, python-format
+msgid "Port %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:59
+#, python-format
+msgid "Failed to create a port for network %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:84
+#, python-format
+msgid "Port %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:89
+#, python-format
+msgid "Failed to update port %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:34
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:6
+msgid "Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:35
+#: dashboards/admin/networks/ports/tables.py:83
+#: dashboards/project/networks/ports/tables.py:53
+msgid "Ports"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:41
+#: dashboards/admin/networks/subnets/tables.py:39
+#: dashboards/project/networks/subnets/tables.py:51
+#, python-format
+msgid "Failed to delete subnet %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:51
+#: dashboards/admin/networks/templates/networks/ports/_create.html:8
+#: dashboards/admin/networks/templates/networks/ports/_create.html:23
+#: dashboards/admin/networks/templates/networks/ports/create.html:3
+#: dashboards/admin/networks/templates/networks/ports/create.html:6
+msgid "Create Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:62
+#: dashboards/admin/networks/templates/networks/ports/_update.html:7
+msgid "Edit Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:75
+#: dashboards/project/networks/ports/tables.py:42
+msgid "Fixed IPs"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:76
+#: dashboards/project/networks/ports/tables.py:43
+msgid "Device Attached"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tabs.py:32
+#: dashboards/admin/overview/panel.py:29
+#: dashboards/admin/overview/templates/overview/usage.html:6
+#: dashboards/project/images_and_snapshots/images/tabs.py:27
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:27
+#: dashboards/project/instances/tabs.py:26
+#: dashboards/project/networks/ports/tabs.py:32
+#: dashboards/project/networks/subnets/tabs.py:32
+#: dashboards/project/overview/panel.py:29
+#: dashboards/project/overview/templates/overview/usage.html:6
+#: dashboards/project/volumes/tabs.py:27
+msgid "Overview"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tabs.py:42
+#: dashboards/project/networks/ports/tabs.py:42
+msgid "Unable to retrieve port details."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:49
+#: dashboards/admin/networks/subnets/views.py:49
+#: dashboards/project/networks/subnets/views.py:54
+msgid "Unable to retrieve network."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:82
+msgid "Unable to retrieve port details"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/forms.py:43
+#, python-format
+msgid "Failed to retrieve network %s for a subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:32
+#: dashboards/project/networks/subnets/tables.py:44
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:6
+msgid "Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:33
+#: dashboards/admin/networks/subnets/tables.py:81
+#: dashboards/project/networks/subnets/tables.py:45
+#: dashboards/project/networks/subnets/tables.py:104
+msgid "Subnets"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:49
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:8
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:23
+#: dashboards/admin/networks/templates/networks/subnets/create.html:3
+#: dashboards/admin/networks/templates/networks/subnets/create.html:6
+#: dashboards/project/networks/workflows.py:53
+#: dashboards/project/networks/subnets/tables.py:61
+#: dashboards/project/networks/templates/networks/subnets/_create.html:8
+#: dashboards/project/networks/templates/networks/subnets/_create.html:23
+#: dashboards/project/networks/templates/networks/subnets/create.html:3
+#: dashboards/project/networks/templates/networks/subnets/create.html:6
+msgid "Create Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:60
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:7
+#: dashboards/project/networks/subnets/tables.py:72
+#: dashboards/project/networks/templates/networks/subnets/_update.html:7
+msgid "Edit Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:72
+#: dashboards/project/access_and_security/security_groups/forms.py:91
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:15
+msgid "CIDR"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:73
+#: dashboards/project/networks/workflows.py:66
+#: dashboards/project/networks/subnets/forms.py:53
+#: dashboards/project/networks/subnets/tables.py:85
+msgid "IP Version"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:74
+#: dashboards/project/networks/subnets/forms.py:54
+#: dashboards/project/networks/subnets/forms.py:104
+#: dashboards/project/networks/subnets/tables.py:86
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:19
+msgid "Gateway IP"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/views.py:82
+#: dashboards/project/networks/subnets/views.py:86
+msgid "Unable to retrieve subnet details"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_create.html:18
+#: dashboards/project/networks/templates/networks/_create.html:17
+msgid "Select a name for your network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:16
+#: dashboards/admin/networks/templates/networks/ports/_update.html:21
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:25
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:17
+#: dashboards/project/instances/templates/instances/_update.html:16
+#: dashboards/project/networks/templates/networks/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_update.html:25
+#: dashboards/settings/ec2/templates/ec2/download_form.html:17
+#: dashboards/settings/project/templates/project/_openrc.html:24
+#: dashboards/settings/user/templates/user/_settings.html:17
+msgid "Description:"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:17
+#: dashboards/project/networks/templates/networks/_update.html:17
+msgid "You may update the editable properties of your network here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:22
+#: dashboards/admin/networks/templates/networks/ports/_update.html:27
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:31
+#: dashboards/project/instances/templates/instances/_update.html:22
+#: dashboards/project/networks/templates/networks/_update.html:22
+#: dashboards/project/networks/templates/networks/subnets/_update.html:31
+msgid "Save Changes"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/update.html:3
+#: dashboards/admin/networks/templates/networks/update.html:6
+#: dashboards/project/networks/templates/networks/update.html:3
+#: dashboards/project/networks/templates/networks/update.html:6
+msgid "Update Network"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_create.html:18
+msgid ""
+"You can create a port for the network. If you specify device ID to be "
+"attached, the device specified will be attached to the port created."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_update.html:22
+msgid "You may update the editable properties of your port here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/update.html:3
+#: dashboards/admin/networks/templates/networks/ports/update.html:6
+msgid "Update Port"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:18
+#: dashboards/project/networks/templates/networks/subnets/_create.html:18
+msgid ""
+"You can create a subnet for the network. Any network address can be "
+"specified unless the network address does not overlap other subnets in the "
+"network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:14
+#: dashboards/project/networks/workflows.py:58
+#: dashboards/project/networks/subnets/forms.py:45
+#: dashboards/project/networks/subnets/tables.py:84
+#: dashboards/project/networks/templates/networks/subnets/_update.html:14
+msgid "Network Address"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:17
+#: dashboards/project/networks/templates/networks/subnets/_update.html:16
+msgid "IP version"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:26
+#: dashboards/project/networks/templates/networks/subnets/_update.html:26
+msgid "You may update the editable properties of your subnet here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/index.html:3
+#: dashboards/admin/networks/templates/networks/subnets/index.html:6
+#: dashboards/project/networks/templates/networks/detail.html:3
+msgid "Network Detail"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/update.html:3
+#: dashboards/admin/networks/templates/networks/subnets/update.html:6
+#: dashboards/project/networks/templates/networks/subnets/update.html:3
+#: dashboards/project/networks/templates/networks/subnets/update.html:6
+msgid "Update Subnet"
+msgstr ""
+
+#: dashboards/admin/overview/templates/overview/usage.html:3
+msgid "Usage Overview"
+msgstr ""
+
+#: dashboards/admin/overview/templates/overview/usage.html:12
+msgid "Monitoring"
+msgstr ""
+
+#: dashboards/admin/projects/panel.py:29
+#: dashboards/admin/projects/tables.py:66
+#: dashboards/admin/projects/tables.py:95
+#: dashboards/admin/projects/templates/projects/index.html:8
+#: templates/403.html:24 templates/404.html:23 templates/500.html:23
+msgid "Projects"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:19
+msgid "Modify Users"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:32
+msgid "View Usage"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:39
+#: dashboards/admin/projects/templates/projects/_create.html:8
+#: dashboards/admin/projects/templates/projects/_create.html:23
+#: dashboards/admin/projects/templates/projects/create.html:6
+msgid "Create Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:46
+#: dashboards/admin/projects/workflows.py:269
+#: dashboards/admin/projects/templates/projects/update.html:3
+#: dashboards/admin/projects/templates/projects/update.html:6
+msgid "Edit Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:90
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:60
+#: dashboards/project/networks/templates/networks/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:15
+msgid "Project ID"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:91
+#: dashboards/admin/projects/workflows.py:76
+#: dashboards/admin/projects/workflows.py:251
+#: dashboards/admin/services/tables.py:42 dashboards/admin/users/tables.py:40
+#: dashboards/admin/users/tables.py:115
+msgid "Enabled"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:104
+msgid "Remove"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:105
+msgid "Removed"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:106 dashboards/admin/users/tables.py:41
+#: dashboards/admin/users/tables.py:75
+#: dashboards/project/instances/workflows.py:39
+msgid "User"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:107 dashboards/admin/users/panel.py:29
+#: dashboards/admin/users/tables.py:42 dashboards/admin/users/tables.py:76
+#: dashboards/admin/users/tables.py:122
+#: dashboards/admin/users/templates/users/index.html:8
+msgid "Users"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:125
+msgid "Unable to retrieve role information."
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:130
+msgid "Roles"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:134
+msgid "Users For Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:142
+msgid "Add To Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:154
+msgid "Add New Users"
+msgstr ""
+
+#: dashboards/admin/projects/views.py:67
+msgid "Unable to retrieve project information."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:87
+msgid "Unable to retrieve project list."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:110
+msgid "Unable to retrieve users."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:154
+msgid "Unable to retrieve default quota values."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:182
+msgid "Unable to retrieve project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:37
+msgid "Injected File Content Bytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:38
+msgid "Metadata Items"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:41
+msgid "Injected Files"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:44
+#: dashboards/admin/volumes/panel.py:9 dashboards/admin/volumes/tables.py:15
+#: dashboards/admin/volumes/templates/volumes/index.html:3
+#: dashboards/admin/volumes/templates/volumes/index.html:6
+#: dashboards/project/volumes/panel.py:25
+#: dashboards/project/volumes/tables.py:38
+#: dashboards/project/volumes/tables.py:171
+#: dashboards/project/volumes/tables.py:183
+#: dashboards/project/volumes/templates/volumes/index.html:3
+#: dashboards/project/volumes/templates/volumes/index.html:6
+msgid "Volumes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:45
+msgid "Gigabytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:46
+msgid "RAM (MB)"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:47
+#: dashboards/project/access_and_security/floating_ips/tables.py:50
+#: dashboards/project/access_and_security/floating_ips/tables.py:128
+msgid "Floating IPs"
+msgstr "Floating IP들"
+
+#: dashboards/admin/projects/workflows.py:50
+msgid "Quota"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:52
+msgid "From here you can set quotas (max limits) for the project."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:81
+#: dashboards/admin/projects/workflows.py:254
+msgid "Project Info"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:82
+#: dashboards/admin/projects/templates/projects/_create.html:18
+msgid "From here you can create a new project to organize users."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:101
+msgid "Unable to retrieve user list. Please try again later."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:155
+#: dashboards/admin/projects/templates/projects/_update_members.html:16
+msgid "Project Members"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:169
+#: dashboards/admin/users/views.py:47
+msgid "Unable to retrieve user list."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:180
+msgid "Add Project"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:181
+msgid "Finish"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:182
+#, python-format
+msgid "Created new project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:183
+#, python-format
+msgid "Unable to create project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:227
+#, python-format
+msgid "Failed to add %s project members and set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:246
+msgid "Unable to set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:256
+msgid "From here you can edit the project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:271
+#, python-format
+msgid "Modified project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:272
+#, python-format
+msgid "Unable to modify project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:342
+#, python-format
+msgid "Failed to modify %s project members and update project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:363
+msgid ""
+"Modified project information and members, but unable to modify project "
+"quotas."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:8
+#: dashboards/admin/projects/templates/projects/add_user.html:3
+#: dashboards/admin/projects/templates/projects/add_user.html:6
+msgid "Add User To Project"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:18
+msgid "Select the user role for the project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:23
+msgid "Add"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:7
+#, python-format
+msgid "Create User for project '%(tenant_name)s'."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:18
+msgid "From here you can create a new user to add to this project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:23
+#: dashboards/admin/users/tables.py:20
+#: dashboards/admin/users/templates/users/_create.html:7
+#: dashboards/admin/users/templates/users/_create.html:22
+#: dashboards/admin/users/templates/users/create.html:7
+msgid "Create User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:7
+#: dashboards/admin/projects/templates/projects/_quotas.html:22
+msgid "Update Quota"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:17
+#, python-format
+msgid ""
+"From here you can edit quotas (max limits) for the project %(tenant.name)s."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update.html:8
+#: dashboards/admin/projects/templates/projects/_update.html:23
+#: dashboards/admin/projects/templates/projects/quotas.html:6
+msgid "Update Project"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update.html:18
+msgid "From here you can edit a project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:7
+msgid ""
+"From here you can add and remove members to this project from the list of "
+"all available users."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:10
+msgid "All Users"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:25
+#: dashboards/admin/projects/templates/projects/_update_members.html:32
+msgid "No users found."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/create_user.html:3
+#: dashboards/admin/projects/templates/projects/create_user.html:6
+msgid "Add New User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:3
+msgid "Project Usage Overview"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:7
+msgid "Project Usage"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/users.html:7
+msgid "Users for Project"
+msgstr ""
+
+#: dashboards/admin/quotas/panel.py:29 dashboards/admin/quotas/tables.py:36
+msgid "Quotas"
+msgstr ""
+
+#: dashboards/admin/quotas/tables.py:28
+msgid "Quota Name"
+msgstr ""
+
+#: dashboards/admin/quotas/tables.py:29
+msgid "Limit"
+msgstr ""
+
+#: dashboards/admin/quotas/views.py:46
+msgid "Unable to get quota info."
+msgstr ""
+
+#: dashboards/admin/quotas/templates/quotas/index.html:8
+msgid "Default Quotas"
+msgstr ""
+
+#: dashboards/admin/services/panel.py:29
+#: dashboards/admin/services/tables.py:47
+#: dashboards/admin/services/templates/services/index.html:8
+msgid "Services"
+msgstr ""
+
+#: dashboards/admin/services/tables.py:37
+msgid "Id"
+msgstr ""
+
+#: dashboards/admin/services/tables.py:39
+msgid "Service"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:54
+msgid "Passwords do not match."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:62 dashboards/admin/users/forms.py:115
+#: dashboards/admin/users/tables.py:108
+msgid "User Name"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:63 dashboards/admin/users/forms.py:116
+#: dashboards/admin/users/tables.py:109
+msgid "Email"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:65 dashboards/admin/users/forms.py:117
+msgid "Password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:70 dashboards/admin/users/forms.py:124
+msgid "Confirm Password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:73 dashboards/admin/users/forms.py:127
+msgid "Primary Project"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:75
+msgid "Role"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:96
+#, python-format
+msgid "User \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:106
+msgid "Unable to add userto primary project."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:110
+msgid "Unable to create user."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:151
+msgid "name"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:151
+msgid "email"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:160
+msgid "primary project"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:173
+#, python-format
+msgid "The user %s has no role defined for"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:181
+msgid "password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:190
+msgid "User has been updated successfully."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:194
+#, python-format
+msgid "Unable to update %(attributes)s for the user."
+msgstr ""
+
+#: dashboards/admin/users/tables.py:32
+#: dashboards/project/images_and_snapshots/images/tables.py:68
+msgid "Edit"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:39
+msgid "Enable"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:39
+msgid "Disable"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:40
+msgid "Disabled"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:63
+msgid "You cannot disable the user you are currently logged in as."
+msgstr ""
+
+#: dashboards/admin/users/tables.py:114
+msgid "User ID"
+msgstr ""
+
+#: dashboards/admin/users/views.py:70
+msgid "Unable to update user."
+msgstr ""
+
+#: dashboards/admin/users/views.py:104
+msgid "Unable to retrieve user roles."
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_create.html:17
+msgid "From here you can create a new user and assign them to a project."
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_update.html:7
+#: dashboards/admin/users/templates/users/_update.html:22
+#: dashboards/admin/users/templates/users/update.html:7
+msgid "Update User"
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_update.html:17
+msgid ""
+"From here you can edit the user's details, including their default project."
+msgstr ""
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:3
+#: dashboards/project/volumes/templates/volumes/detail.html:3
+msgid "Volume Details"
+msgstr ""
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:6
+#: dashboards/project/volumes/templates/volumes/detail.html:6
+msgid "Volume Detail"
+msgstr ""
+
+#: dashboards/project/dashboard.py:24
+msgid "Manage Compute"
+msgstr ""
+
+#: dashboards/project/dashboard.py:35
+msgid "Object Store"
+msgstr "Object Store"
+
+#: dashboards/project/access_and_security/panel.py:26
+#: dashboards/project/instances/workflows.py:348
+msgid "Access & Security"
+msgstr ""
+
+#: dashboards/project/access_and_security/views.py:51
+msgid "Unable to retrieve keypair list."
+msgstr ""
+
+#: dashboards/project/access_and_security/views.py:60
+#: dashboards/project/access_and_security/security_groups/views.py:74
+msgid "Unable to retrieve security groups."
+msgstr ""
+
+#: dashboards/project/access_and_security/views.py:69
+#: dashboards/project/access_and_security/floating_ips/workflows.py:49
+msgid "Unable to retrieve floating IP addresses."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:32
+msgid "Pool"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:43
+#, python-format
+msgid "Allocated Floating IP %(ip)s."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:47
+msgid "Unable to allocate Floating IP."
+msgstr "Floating IP를 할당할 수 없습니다."
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:37
+msgid "Allocate IP To Project"
+msgstr "프로젝트에 IP 할당 "
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:47
+msgid "Release"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:48
+msgid "Released"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:49
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:22
+msgid "Floating IP"
+msgstr "Floating IP"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:6
+#: dashboards/project/instances/tables.py:219
+msgid "Associate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:76
+msgid "Disassociate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:90
+#, python-format
+msgid "Successfully disassociated Floating IP: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:94
+msgid "Unable to disassociate floating IP."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:114
+#: dashboards/project/access_and_security/floating_ips/workflows.py:36
+#: dashboards/project/instances/tables.py:69
+#: dashboards/project/instances/tables.py:89
+#: dashboards/project/instances/tables.py:106
+#: dashboards/project/instances/tables.py:135
+#: dashboards/project/volumes/tables.py:206
+msgid "Instance"
+msgstr "인스턴스"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:117
+msgid "Floating IP Pool"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:65
+msgid "Unable to retrieve floating IP pools."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:68
+msgid "No floating IP pools available."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:40
+msgid "Select the IP address you wish to associate with the selected instance."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:53
+msgid "Select an IP address"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:55
+msgid "No IP addresses available"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:76
+#: dashboards/project/volumes/forms.py:160
+msgid "Select an instance"
+msgstr "인스턴스 선택"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:78
+#: dashboards/project/volumes/forms.py:162
+msgid "No instances available"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:97
+msgid "Manage Floating IP Associations"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:98
+msgid "Associate"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:99
+#, python-format
+msgid "IP address %s associated."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:100
+#, python-format
+msgid "Unable to associate IP address %s."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:38
+#: dashboards/project/access_and_security/keypairs/forms.py:49
+#: dashboards/project/access_and_security/keypairs/tables.py:52
+msgid "Keypair Name"
+msgstr "키페어 이름 "
+
+#: dashboards/project/access_and_security/keypairs/forms.py:40
+msgid ""
+"Keypair names may only contain letters, numbers, underscores and hyphens."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:51
+msgid "Public Key"
+msgstr "공용키"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:60
+#, python-format
+msgid "Successfully imported public key: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:65
+msgid "Unable to import keypair."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:30
+#: dashboards/project/instances/tables.py:295
+#: dashboards/project/instances/workflows.py:335
+msgid "Keypair"
+msgstr "키페어"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:31
+#: dashboards/project/access_and_security/keypairs/tables.py:60
+msgid "Keypairs"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:39
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html:6
+msgid "Import Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:46
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html:6
+msgid "Create Keypair"
+msgstr "키페어 생성"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:53
+msgid "Fingerprint"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/views.py:74
+#, python-format
+msgid "Unable to create keypair: %(exc)s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:46
+#, python-format
+msgid "Successfully created security group: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:52
+msgid "Unable to create security group."
+msgstr "보안 그룹 (Security Group)을 생성할 수 없습니다."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:57
+#: dashboards/project/access_and_security/security_groups/tables.py:93
+msgid "IP Protocol"
+msgstr "IP 프로토콜"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:61
+msgid "The protocol which this rule should be applied to."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:65
+#: dashboards/project/access_and_security/security_groups/forms.py:71
+#: dashboards/project/access_and_security/security_groups/tables.py:95
+msgid "From Port"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:66
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP type in the range (-1: 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:72
+#: dashboards/project/images_and_snapshots/images/tables.py:115
+msgid "Type"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:74
+#: dashboards/project/access_and_security/security_groups/forms.py:80
+#: dashboards/project/access_and_security/security_groups/tables.py:96
+msgid "To Port"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:75
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP code in the range (-1: 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:81
+msgid "Code"
+msgstr "코드 "
+
+#: dashboards/project/access_and_security/security_groups/forms.py:84
+msgid "Source Group"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:86
+msgid ""
+"To specify an allowed IP range, select CIDR. To allow access from all "
+"members of another security group select Source Group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:94
+msgid "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:121
+msgid "The ICMP type is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:124
+msgid "The ICMP code is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:127
+msgid "The ICMP type not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:130
+msgid "The ICMP code not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:134
+msgid "The \"from\" port number is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:137
+msgid "The \"to\" port number is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:140
+msgid ""
+"The \"to\" port number must be greater than or equal to the \"from\" port "
+"number."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:146
+msgid "Either CIDR or Source Group may be specified, but not both."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:168
+#, python-format
+msgid "Successfully added rule: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:173
+msgid "Unable to add rule to security group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:31
+msgid "Security Group"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:32
+#: dashboards/project/access_and_security/security_groups/tables.py:66
+#: dashboards/project/instances/workflows.py:340
+#: dashboards/project/instances/templates/instances/_detail_overview.html:49
+msgid "Security Groups"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:45
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html:6
+msgid "Create Security Group"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:52
+msgid "Edit Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:72
+msgid "Rule"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:73
+msgid "Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:97
+msgid "Source"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:107
+msgid "Security Group Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/views.py:60
+msgid "Unable to retrieve security group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/views.py:80
+#, python-format
+msgid "%s (current)"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/index.html:6
+msgid "Access &amp; Security"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:8
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html:3
+msgid "Allocate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:18
+msgid "Allocate a floating IP from a given floating ip pool."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:20
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:19
+msgid "Project Quotas"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:31
+msgid "Allocate IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:17
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:17
+msgid ""
+"Keypairs are ssh credentials which are injected into images when they are "
+"launched. Creating a new key pair registers the public key and downloads the "
+"private key (a .pem file)."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:18
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:18
+msgid "Protect and use the key as you would any normal ssh private key."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:6
+msgid "Download Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:11
+#, python-format
+msgid ""
+"The keypair &quot;%(keypair_name)s&quot; should download automatically. If "
+"not use the link below."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:15
+#, python-format
+msgid "Download keypair &quot;%(keypair_name)s&quot;"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:18
+msgid "From here you can create a new security group"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:9
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html:6
+msgid "Edit Security Group Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:12
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:19
+msgid "Add Rule"
+msgstr ""
+
+#: dashboards/project/containers/browsers.py:26
+msgid "Swift"
+msgstr ""
+
+#: dashboards/project/containers/browsers.py:29
+#: dashboards/project/containers/tables.py:40
+msgid "Container"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:39
+msgid "Slash is not an allowed character."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:49
+#: dashboards/project/containers/tables.py:121
+msgid "Container Name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:57
+msgid "Container created successfully."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:68
+msgid "Folder created successfully."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:71
+msgid "Unable to create container."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:79
+#: dashboards/project/containers/tables.py:253
+msgid "Object Name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:81
+msgid "File"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:95
+msgid "Object was successfully uploaded."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:98
+msgid "Unable to upload object."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:102
+msgid "Destination container"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:106
+msgid "Destination object name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:137
+#: dashboards/project/containers/forms.py:163
+msgid "Unable to copy object."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:153
+#, python-format
+msgid "Copied \"%(orig)s\" to \"%(dest)s\" as \"%(new)s\"."
+msgstr ""
+
+#: dashboards/project/containers/panel.py:29
+#: dashboards/project/containers/tables.py:41
+#: dashboards/project/containers/tables.py:128
+#: dashboards/project/containers/templates/containers/index.html:7
+msgid "Containers"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:62
+#: dashboards/project/containers/templates/containers/_create.html:7
+#: dashboards/project/containers/templates/containers/_create.html:22
+#: dashboards/project/containers/templates/containers/create.html:6
+msgid "Create Container"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:69
+msgid "View Container"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:81
+#: dashboards/project/containers/templates/containers/_upload.html:23
+#: dashboards/project/containers/templates/containers/upload.html:3
+msgid "Upload Object"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:137
+#: dashboards/project/containers/tables.py:156
+msgid "Object"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:138
+#: dashboards/project/containers/tables.py:157
+#: dashboards/project/containers/tables.py:263
+msgid "Objects"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:149
+msgid "Folder"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:150
+msgid "Folders"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:163
+msgid "Copy"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:176
+msgid "Download"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:232
+msgid "Create Folder"
+msgstr ""
+
+#: dashboards/project/containers/views.py:53
+msgid "Unable to retrieve container list."
+msgstr ""
+
+#: dashboards/project/containers/views.py:82
+msgid "Unable to retrieve object list."
+msgstr ""
+
+#: dashboards/project/containers/views.py:166
+msgid "Unable to retrieve object."
+msgstr ""
+
+#: dashboards/project/containers/views.py:200
+msgid "Unable to list containers."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_copy.html:7
+#: dashboards/project/containers/templates/containers/_copy.html:22
+#: dashboards/project/containers/templates/containers/copy.html:3
+#: dashboards/project/containers/templates/containers/copy.html:6
+msgid "Copy Object"
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_copy.html:17
+msgid ""
+"Make a new copy of an existing object to store in this or another container. "
+"You may also specify a path at which the new copy should live inside of the "
+"selected container."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_create.html:17
+msgid ""
+"A container is a storage compartment for your data and provides a way for "
+"you to organize your data. You can think of a container as a folder in "
+"Windows &reg; or a directory in UNIX &reg;. The primary difference between a "
+"container and these other file system concepts is that containers cannot be "
+"nested. You can, however, create an unlimited number of containers within "
+"your account. Data must be stored in a container so you must have at least "
+"one container defined in your account prior to uploading data."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:8
+msgid "Upload Object To Container"
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:18
+msgid ""
+"An object is the basic storage entity and any optional metadata that "
+"represents the files you store in the OpenStack Object Storage system. When "
+"you upload data to OpenStack Object Storage, the data is stored as-is (no "
+"compression or encryption) and consists of a location (container), the "
+"object's name, and any metadata consisting of key/value pairs."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/upload.html:6
+msgid "Upload Objects"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/panel.py:26
+msgid "Images & Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:63
+msgid "Unable to retrieve images."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:74
+msgid "Unable to retrieve snapshots."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:82
+#: dashboards/project/volumes/forms.py:65
+msgid "Unable to retrieve volume snapshots."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:42
+msgid "Image Location"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:43
+msgid "An external (HTTP) URL to load the image from."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:46
+#: dashboards/project/images_and_snapshots/images/forms.py:130
+#: dashboards/project/images_and_snapshots/images/tables.py:126
+msgid "Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:50
+msgid "AKI - Amazon Kernel Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:53
+msgid "AMI - Amazon Machine Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:56
+msgid "ARI - Amazon Ramdisk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:59
+msgid "ISO - Optical Disk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:61
+msgid "QCOW2 - QEMU Emulator"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:68
+msgid "Minimum Disk (GB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:69
+#: dashboards/project/images_and_snapshots/images/forms.py:76
+msgid ""
+"The minimum disk size required to boot the image. If unspecified, this value "
+"defaults to 0 (no minimum)."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:75
+msgid "Minimum Ram (MB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:82
+#: dashboards/project/images_and_snapshots/images/forms.py:134
+#: dashboards/project/images_and_snapshots/images/tables.py:123
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:15
+msgid "Public"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:106
+#, python-format
+msgid "Your image %s has been queued for creation."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:110
+msgid "Unable to create new image."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:116
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:48
+msgid "Kernel ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:121
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:52
+msgid "Ramdisk ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:126
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:44
+msgid "Architecture"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:138
+#, python-format
+msgid "Unable to update image \"%s\"."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:162
+msgid "Image was successfully updated."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tables.py:34
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:33
+#: dashboards/project/instances/workflows.py:455
+msgid "Launch"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tables.py:46
+#: dashboards/project/images_and_snapshots/images/tables.py:82
+#: dashboards/project/instances/workflows.py:168
+#: dashboards/project/instances/workflows.py:173
+msgid "Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tables.py:61
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:31
+msgid "Create Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tabs.py:38
+msgid "Unable to retrieve image details."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/views.py:61
+msgid "Unable to retrieve image."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:37
+msgid "Instance ID"
+msgstr "인스턴스 ID"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:40
+#: dashboards/project/volumes/forms.py:193
+msgid "Snapshot Name"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:50
+#, python-format
+msgid "Snapshot \"%(name)s\" created for instance \"%(inst)s\""
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:56
+msgid "Unable to create snapshot."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:48
+#: dashboards/project/instances/workflows.py:107
+#: dashboards/project/instances/workflows.py:169
+msgid "Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:49
+msgid "Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:55
+msgid "Instance Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/views.py:53
+msgid "Unable to retrieve instance."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:6
+msgid "Images &amp; Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:6
+msgid "Create An Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:18
+msgid "Specify an image to upload to the Image Service."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:21
+msgid ""
+"Currently only images available via an HTTP URL are supported. The image "
+"location must be accessible to the Image Service. Compressed image binaries "
+"are supported (.zip and .tar.gz.)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:24
+msgid "Please note: "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:25
+msgid ""
+"The Image Location field MUST be a valid and direct URL to the image binary. "
+"URLs that redirect or serve error pages will result in unusable images."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:3
+msgid "Image Overview"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:6
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:7
+#: dashboards/project/instances/templates/instances/_detail_overview.html:6
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:6
+msgid "Info"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:17
+msgid "Checksum"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:19
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:39
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:28
+msgid "Created"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:21
+msgid "Updated"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:27
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:34
+#: dashboards/project/instances/templates/instances/_detail_overview.html:19
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:23
+msgid "Specs"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:32
+msgid "Container Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:34
+msgid "Disk Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:40
+msgid "Custom Properties"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:56
+msgid "Euca2ools state"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:64
+msgid "Image Type"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html:4
+msgid "Image Detail "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:8
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:3
+#: dashboards/project/instances/tables.py:179
+#: dashboards/project/volumes/tables.py:76
+msgid "Create Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:18
+msgid "Snapshots preserve the disk state of a running instance."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:20
+#: dashboards/project/instances/workflows.py:75
+#: dashboards/project/instances/workflows.py:110
+#: dashboards/project/instances/templates/instances/_detail_overview.html:93
+#: dashboards/project/volumes/tables.py:37
+#: dashboards/project/volumes/tables.py:182
+msgid "Volume"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:38
+#: dashboards/project/instances/templates/instances/_detail_overview.html:29
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:27
+msgid "GB"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:6
+msgid "Create a Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:3
+msgid "Volume Snapshot Details"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:6
+msgid "Volume Snapshot Detail"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:34
+#: dashboards/project/instances/workflows.py:76
+msgid "Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:35
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:85
+msgid "Volume Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:43
+#: dashboards/project/volumes/tables.py:59
+#: dashboards/project/volumes/templates/volumes/_create.html:8
+#: dashboards/project/volumes/templates/volumes/_create.html:55
+msgid "Create Volume"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:80
+#: dashboards/project/volumes/forms.py:26
+msgid "Volume Name"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:41
+#, fuzzy
+msgid "Unable to retrieve snapshot details."
+msgstr "인스턴스 목록을 불러올 수 없습니다."
+
+#: dashboards/project/instances/forms.py:45
+#, python-format
+msgid "Instance \"%s\" updated."
+msgstr ""
+
+#: dashboards/project/instances/forms.py:50
+msgid "Unable to update instance."
+msgstr ""
+
+#: dashboards/project/instances/tables.py:67
+msgid "Terminate"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:68
+msgid "Scheduled termination of"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:87
+msgid "Reboot"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:88
+msgid "Rebooted"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:104
+msgid "Pause"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:104
+msgid "Unpause"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:105
+msgid "Paused"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:105
+msgid "Unpaused"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:133
+msgid "Suspend"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:133
+msgid "Resume"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:134
+msgid "Suspended"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:134
+msgid "Resumed"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:162
+#: dashboards/project/instances/workflows.py:454
+#: dashboards/project/instances/templates/instances/launch.html:3
+#: dashboards/project/instances/templates/instances/launch.html:6
+msgid "Launch Instance"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:169
+#: dashboards/project/instances/templates/instances/_update.html:7
+msgid "Edit Instance"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:189
+msgid "VNC Console"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:204
+msgid "View Log"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:252
+#, python-format
+msgid "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disk"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:259
+#: dashboards/project/instances/tables.py:266
+msgid "Not available"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:36
+msgid "Log"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:48
+#: dashboards/project/instances/views.py:106
+#, python-format
+msgid "Unable to get log for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:55
+msgid "VNC"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:70
+#: dashboards/project/instances/views.py:122
+#, python-format
+msgid "Unable to get VNC console for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/views.py:59
+msgid "Unable to retrieve instances."
+msgstr ""
+
+#: dashboards/project/instances/views.py:144
+msgid "Unable to retrieve instance details."
+msgstr ""
+
+#: dashboards/project/instances/views.py:179
+#, python-format
+msgid "Unable to retrieve details for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:53
+msgid "Project & User"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:66
+msgid "Don't boot from a volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:67
+msgid "Boot from volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:68
+msgid "Boot from volume snapshot (creates a new volume)."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:72
+#: dashboards/project/instances/workflows.py:90
+msgid "Volume Options"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:78
+#: dashboards/project/volumes/forms.py:126
+msgid "Device Name"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:81
+msgid "Volume mount point (e.g. 'vda' mounts at '/dev/vda')."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:83
+msgid "Delete on Terminate"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:86
+msgid "Delete volume on instance terminate"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:100
+#, python-format
+msgid "Please choose a volume, or select %s."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:117
+msgid "Select Volume"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:125
+msgid "Unable to retrieve list of volumes."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:129
+msgid "Select Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:138
+msgid "Unable to retrieve list of volume snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:171
+msgid "Instance Source"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:174
+msgid "Instance Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:178
+msgid "Size of image to launch."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:179
+msgid "Instance Count"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:182
+msgid "Number of instances to launch."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:185
+msgid "Details"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:198
+msgid ""
+"There are no image sources available; you must first create an image before "
+"attempting to launch an instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:203
+msgid "Please select an option for the instance source."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:212
+msgid ""
+"Launching multiple instances is only supported for images and instance "
+"snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:229
+msgid "Unable to retrieve public images."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:244
+msgid "Unable to retrieve images for the current project."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:267
+msgid "Select Image"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:269
+msgid "No images available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:278
+msgid "Select Instance Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:280
+msgid "No snapshots available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:291
+msgid "Unable to retrieve instance flavors."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:304 usage/base.py:114
+msgid "Unable to retrieve quota information."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:337
+msgid "Which keypair to use for authentication."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:344
+msgid "Launch instance in these security groups."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:349
+msgid ""
+"Control access to your instance via keypairs, security groups, and other "
+"mechanisms."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:359
+msgid "Unable to retrieve keypairs."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:361
+msgid "Select a keypair"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:363
+msgid "No keypairs available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:372
+msgid "Unable to retrieve list of security groups"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:392
+msgid "Customization Script"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:394
+msgid ""
+"A script or set of commands to be executed after the instance has been built "
+"(max 16kb)."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:401
+msgid "Post-Creation"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:415
+msgid "Launch instance withthese networks"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:419
+msgid "Networking"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:421
+msgid "Select networks for your instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:433
+msgid "Unable to retrieve networks."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:456
+#, python-format
+msgid "Launched %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:457
+#, python-format
+msgid "Unable to launch %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:470
+#, python-format
+msgid "%s instances"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:473
+msgid "instance"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:4
+msgid "Instance Console Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:7
+msgid "Log Length"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:9
+msgid "Go"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:11
+msgid "View Full Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:3
+msgid "Instance Overview"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:27
+msgid "VCPU"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:28
+#: usage/tables.py:20
+msgid "Disk"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:34
+msgid "IP Addresses"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:59
+msgid "No rules defined."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:68
+msgid "Meta"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:71
+msgid "Key Name"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:84
+msgid "Volumes Attached"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:88
+#: dashboards/project/volumes/tables.py:167
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:38
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:45
+msgid "Attached To"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:90
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:42
+msgid "on"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:94
+msgid "No volumes attached."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:3
+msgid "Instance VNC Console"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid ""
+"If VNC console is not responding to keyboard input: click the grey status "
+"bar below."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid "Click here to show only VNC"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:8
+msgid "VNC console is currently unavailabe. Please try again later."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:9
+msgid "Reload"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:2
+msgid ""
+"You can customize your instance after it's launched using the options "
+"available here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:3
+msgid ""
+"The \"Customization Script\" field is analogous to \"User Data\" in other "
+"systems."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:3
+msgid "Specify the details for launching an instance."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:4
+msgid ""
+"The chart below shows the resources used by this project in relation to the "
+"project's quotas."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:6
+msgid "Flavor Details"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+msgid "Total Disk"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "MB"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:21
+msgid "Number of Instances"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:29
+msgid "Number of VCPUs"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "Total RAM"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_volumes_help.html:3
+msgid ""
+"An instance can be launched with varying types of attached storage. You may "
+"select from those options here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_update.html:17
+msgid "You may update the editable properties of your instance here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/detail.html:3
+msgid "Instance Detail"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/update.html:3
+#: dashboards/project/instances/templates/instances/update.html:6
+msgid "Update Instance"
+msgstr ""
+
+#: dashboards/project/networks/tables.py:81
+msgid "Add Subnet"
+msgstr ""
+
+#: dashboards/project/networks/views.py:86
+msgid "Unable to retrieve network details."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:37
+msgid "Network Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:42
+msgid ""
+"From here you can create a new network.\n"
+"In addition a subnet associated with the network can be created in the next "
+"panel."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:56
+msgid "Subnet Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:61
+#: dashboards/project/networks/subnets/forms.py:48
+msgid "Network address in CIDR format (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:67
+msgid "Gateway IP (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:70
+#: dashboards/project/networks/subnets/forms.py:57
+#: dashboards/project/networks/subnets/forms.py:107
+msgid "IP address of Gateway (e.g. 192.168.0.1)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:77
+msgid ""
+"You can create a subnet associated with the new network, in which case "
+"\"Network Address\" must be specified. If you wish to create a network "
+"WITHOUT a subnet, uncheck the \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:89
+msgid "Specify \"Network Address\" or clear \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:94
+#: dashboards/project/networks/subnets/forms.py:70
+msgid "Network Address and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:98
+#: dashboards/project/networks/subnets/forms.py:74
+#: dashboards/project/networks/subnets/forms.py:119
+msgid "Gateway IP and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:112
+msgid "Create"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:113
+#, python-format
+msgid "Created network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:114
+#, python-format
+msgid "Unable to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:130
+#, python-format
+msgid "Network \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:133
+#, python-format
+msgid "Failed to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:152
+#, python-format
+msgid "Subnet \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:155
+#, python-format
+msgid "Failed to create subnet \"%(sub)s\" for network \"%(net)s\"."
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Attached"
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Detached"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:85
+#, python-format
+msgid "Subnet %s was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:90
+#, python-format
+msgid "Failed to create subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:131
+#, python-format
+msgid "Subnet %s was successfully updated."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:136
+#, python-format
+msgid "Failed to update subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/tabs.py:42
+msgid "Unable to retrieve subnet details."
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/_detail_overview.html:3
+msgid "Network Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/detail.html:6
+msgid "Network Detail: "
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:3
+msgid "Port Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:17
+msgid "Fixed IP"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:21
+msgid "IP address:"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:22
+msgid "Subnet ID"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:28
+msgid "Mac Address"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/detail.html:3
+#: dashboards/project/networks/templates/networks/ports/detail.html:6
+msgid "Port Detail"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:3
+msgid "Subnet Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:21
+msgid "IP allocation pool"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:24
+msgid "Start"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:25
+msgid " - End"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/detail.html:3
+#: dashboards/project/networks/templates/networks/subnets/detail.html:6
+msgid "Subnet Detail"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:29
+msgid "Size (GB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:30
+msgid "Use snapshot as a source"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:49
+#, python-format
+msgid "Volume size must be equal to or greater than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:54
+msgid "Unable to load the specified snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:59
+msgid "Choose a snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:83
+#, python-format
+msgid "The volume size cannot be less than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:92
+#, python-format
+msgid ""
+"A volume of %(req)iGB cannot be created as you only have %(avail)iGB of your "
+"quota available."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:99
+msgid "You are already using all of your available volumes."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:115
+msgid "Unable to create volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:123
+msgid "Attach to Instance"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:124
+msgid "Select an instance to attach to."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:168
+msgid "Unknown instance (None)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:179
+#, python-format
+msgid "Attaching volume %(vol)s to instance %(inst)s on %(dev)s."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:188
+msgid "Unable to attach volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:212
+#, python-format
+msgid "Creating volume snapshot \"%s\""
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:218
+msgid "Unable to create volume snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:46
+#, python-format
+msgid "Unable to delete volume \"%s\". One or more snapshots depend on it."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:66
+msgid "Edit Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:93
+#, python-format
+msgid "%sGB"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:106
+#: dashboards/project/volumes/views.py:149
+msgid "Unable to retrieve attachment information."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:123
+#, python-format
+msgid "Attached to %(instance)s on %(dev)s"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:180
+msgid "Detach"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:181
+msgid "Detaching"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:216
+#, python-format
+msgid "%(dev)s on instance %(instance_name)s"
+msgstr ""
+
+#: dashboards/project/volumes/tabs.py:42
+msgid "Unable to retrieve volume details."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:50
+msgid "Unable to retrieve volume list."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:58
+msgid "Unable to retrieve volume/instance attachment information"
+msgstr ""
+
+#: dashboards/project/volumes/views.py:130
+#: dashboards/project/volumes/views.py:140
+msgid "Unable to retrieve volume information."
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:9
+#: dashboards/project/volumes/templates/volumes/attach.html:6
+msgid "Manage Volume Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:13
+msgid "Attach To Instance"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:22
+msgid "Attach Volume"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:20
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:18
+msgid "Volumes are block devices that can be attached to instances."
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:22
+msgid "Volume Quotas"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:25
+msgid "Total Gigabytes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:34
+msgid "Number of Volumes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:8
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:23
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:3
+msgid "Create Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:3
+msgid "Volume Overview"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:34
+msgid "Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:46
+msgid "Not attached"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/create.html:6
+msgid "Create a Volume"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:6
+msgid "Create a Volume Snapshot"
+msgstr ""
+
+#: dashboards/settings/dashboard.py:24 templates/_header.html:4
+msgid "Settings"
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:36 dashboards/settings/project/forms.py:36
+msgid "Select a Project"
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:46
+msgid "Unable to retrieve tenant list."
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:88
+msgid "Unable to fetch EC2 credentials."
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:101
+#, python-format
+msgid "Error writing zipfile: %(exc)s"
+msgstr ""
+
+#: dashboards/settings/ec2/panel.py:25
+msgid "EC2 Credentials"
+msgstr ""
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:8
+#: dashboards/settings/ec2/templates/ec2/download_form.html:23
+#: dashboards/settings/ec2/templates/ec2/index.html:3
+#: dashboards/settings/ec2/templates/ec2/index.html:6
+msgid "Download EC2 Credentials"
+msgstr ""
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:18
+msgid ""
+"Clicking \"Download EC2 Credentials\" will download a zip file which "
+"includes an rc file with your access/secret keys, as well as your x509 "
+"private key and certificate."
+msgstr ""
+
+#: dashboards/settings/project/forms.py:71
+#, python-format
+msgid "Error Downloading RC File: %s"
+msgstr ""
+
+#: dashboards/settings/project/panel.py:25
+#: dashboards/settings/project/templates/project/_openrc.html:8
+#: dashboards/settings/project/templates/project/settings.html:3
+#: dashboards/settings/project/templates/project/settings.html:6
+msgid "OpenStack API"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:27
+msgid "Service Name"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:29
+msgid "Service Endpoint"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:33
+msgid "API Endpoints"
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:15
+msgid "Download OpenStack RC File"
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:25
+msgid ""
+"Download the RC file for the selected project, then type \"source openrc\" "
+"in the terminal to configure your environment to communicate with OpenStack."
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:30
+msgid "Download RC File"
+msgstr ""
+
+#: dashboards/settings/user/forms.py:57
+msgid "Settings saved."
+msgstr ""
+
+#: dashboards/settings/user/panel.py:25
+#: dashboards/settings/user/templates/user/_settings.html:8
+#: dashboards/settings/user/templates/user/settings.html:3
+#: dashboards/settings/user/templates/user/settings.html:6
+msgid "User Settings"
+msgstr ""
+
+#: dashboards/settings/user/templates/user/_settings.html:18
+msgid "From here you can modify dashboard settings for your user."
+msgstr ""
+
#: templates/403.html:4 templates/403.html.py:9
msgid "Forbidden"
msgstr "거부했습니다"
@@ -83,10 +3231,6 @@ msgstr "거부했습니다"
msgid "Home"
msgstr "홈"
-#: templates/403.html:24 templates/404.html:23 templates/500.html:23
-msgid "Projects"
-msgstr "프로젝트"
-
#: templates/404.html:4
msgid "Page Not Found"
msgstr "페이지를 찾을 수 없습니다"
@@ -110,3 +3254,47 @@ msgid ""
msgstr ""
"요청을 처리하는 동안 예상치 못한 에러가 발생하였습니다. 다시 요청해주시기 바"
"랍니다."
+
+#: templates/_header.html:3
+msgid "Logged in as"
+msgstr ""
+
+#: templates/_header.html:6
+msgid "Help"
+msgstr ""
+
+#: templates/_header.html:8
+msgid "Sign Out"
+msgstr ""
+
+#: test/settings.py:50
+msgid "Password must be between 8 and 18 characters."
+msgstr ""
+
+#: usage/base.py:97
+msgid "Unable to retrieve usage information."
+msgstr ""
+
+#: usage/base.py:100
+msgid "You are viewing data for the future, which may or may not exist."
+msgstr ""
+
+#: usage/tables.py:11
+msgid "Download CSV Summary"
+msgstr ""
+
+#: usage/tables.py:25
+msgid "VCPU Hours"
+msgstr ""
+
+#: usage/tables.py:32
+msgid "Disk GB Hours"
+msgstr ""
+
+#: usage/tables.py:40 usage/tables.py:68
+msgid "Usage Summary"
+msgstr ""
+
+#: usage/tables.py:60
+msgid "Uptime"
+msgstr ""
diff --git a/openstack_dashboard/locale/nl_NL/LC_MESSAGES/django.mo b/openstack_dashboard/locale/nl_NL/LC_MESSAGES/django.mo
index e2f27ccc3..0b0c0382f 100644
--- a/openstack_dashboard/locale/nl_NL/LC_MESSAGES/django.mo
+++ b/openstack_dashboard/locale/nl_NL/LC_MESSAGES/django.mo
Binary files differ
diff --git a/openstack_dashboard/locale/nl_NL/LC_MESSAGES/django.po b/openstack_dashboard/locale/nl_NL/LC_MESSAGES/django.po
index 1c59fbfe1..2af82bd35 100644
--- a/openstack_dashboard/locale/nl_NL/LC_MESSAGES/django.po
+++ b/openstack_dashboard/locale/nl_NL/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Horizon\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-09-18 22:18+0000\n"
+"POT-Creation-Date: 2012-10-05 19:30+0000\n"
"PO-Revision-Date: 2012-08-14 08:40+0000\n"
"Last-Translator: Erik-Martijn Kasimier <erik.kasimier@nouveaumedia.nl>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,63 +18,3213 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: settings.py:141
+#: settings.py:142
msgid "Bulgarian (Bulgaria)"
msgstr ""
-#: settings.py:142
+#: settings.py:143
msgid "Czech"
msgstr ""
-#: settings.py:143
+#: settings.py:144
msgid "English"
msgstr "Engels"
-#: settings.py:144
+#: settings.py:145
msgid "Spanish"
msgstr "Spaans"
-#: settings.py:145
+#: settings.py:146
msgid "French"
msgstr "Frans"
-#: settings.py:146
+#: settings.py:147
msgid "Italiano"
msgstr "Italiaans"
-#: settings.py:147
+#: settings.py:148
msgid "Japanese"
msgstr "Japans"
-#: settings.py:148
+#: settings.py:149
msgid "Korean (Korea)"
msgstr ""
-#: settings.py:149
+#: settings.py:150
msgid "Dutch (Netherlands)"
msgstr ""
-#: settings.py:150
+#: settings.py:151
msgid "Polish"
msgstr "Pools"
-#: settings.py:151
+#: settings.py:152
msgid "Portuguese"
msgstr "Portugees"
-#: settings.py:152
+#: settings.py:153
#, fuzzy
msgid "Portuguese (Brazil)"
msgstr "Portugees"
-#: settings.py:153
+#: settings.py:154
msgid "Simplified Chinese"
msgstr "Vereenvoudigd Chinees"
-#: settings.py:154
+#: settings.py:155
msgid "Traditional Chinese"
msgstr "Traditioneel Chinees"
+#: api/keystone.py:56
+#, python-format
+msgid "%(type)s (%(backend)s backend)"
+msgstr ""
+
+#: api/nova.py:191
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(group)s"
+msgstr "TOESTAAN %(from)s:%(to)s van %(group)s"
+
+#: api/nova.py:196
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(cidr)s"
+msgstr "TOESTAAN %(from)s:%(to)s van %(cidr)s"
+
+#: api/nova.py:532
+msgid "Unknown instance"
+msgstr ""
+
+#: api/swift.py:217
+msgid "Unicode is not currently supported for object copy."
+msgstr ""
+"Unicode wordt op dit moment nog niet ondersteund voor het kopieëren van "
+"objecten. "
+
+#: dashboards/admin/dashboard.py:24
+msgid "System Panel"
+msgstr ""
+
+#: dashboards/admin/dashboard.py:30
+msgid "Admin"
+msgstr "Beheerder"
+
+#: dashboards/admin/flavors/forms.py:36 dashboards/admin/networks/forms.py:34
+#: dashboards/admin/networks/forms.py:69
+#: dashboards/admin/networks/ports/forms.py:40
+#: dashboards/admin/networks/ports/forms.py:72
+#: dashboards/admin/networks/ports/tables.py:73
+#: dashboards/admin/networks/subnets/tables.py:70
+#: dashboards/admin/projects/tables.py:87
+#: dashboards/admin/projects/workflows.py:71
+#: dashboards/admin/services/tables.py:38
+#: dashboards/admin/volumes/tables.py:10
+#: dashboards/project/access_and_security/security_groups/forms.py:36
+#: dashboards/project/access_and_security/security_groups/tables.py:58
+#: dashboards/project/images_and_snapshots/images/forms.py:40
+#: dashboards/project/images_and_snapshots/images/forms.py:115
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:9
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:10
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:77
+#: dashboards/project/instances/templates/instances/_detail_overview.html:9
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:9
+#: dashboards/project/networks/forms.py:37
+#: dashboards/project/networks/tables.py:94
+#: dashboards/project/networks/ports/tables.py:40
+#: dashboards/project/networks/subnets/forms.py:43
+#: dashboards/project/networks/subnets/forms.py:102
+#: dashboards/project/networks/subnets/tables.py:82
+#: dashboards/project/networks/templates/networks/_detail_overview.html:7
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:9
+#: dashboards/project/volumes/tables.py:144
+#: dashboards/project/volumes/tables.py:164
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:9
+msgid "Name"
+msgstr "Naam"
+
+#: dashboards/admin/flavors/forms.py:37 dashboards/admin/flavors/tables.py:41
+#: dashboards/admin/projects/workflows.py:39
+#: dashboards/project/instances/templates/instances/_detail_overview.html:26
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:10
+#: usage/tables.py:19
+msgid "VCPUs"
+msgstr "VCPU's"
+
+#: dashboards/admin/flavors/forms.py:38
+msgid "RAM MB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:39
+msgid "Root Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:40
+msgid "Ephemeral Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:50
+msgid "Unable to get unique ID for new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:67
+#, python-format
+msgid "Created flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:71
+msgid "Unable to create flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:92
+#, python-format
+msgid "Updated flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:96
+msgid "Unable to update flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/panel.py:29 dashboards/admin/flavors/tables.py:15
+#: dashboards/admin/flavors/tables.py:52
+#: dashboards/admin/flavors/templates/flavors/index.html:3
+#: dashboards/admin/flavors/templates/flavors/index.html:6
+msgid "Flavors"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:14
+#: dashboards/project/instances/workflows.py:177
+#: dashboards/project/instances/templates/instances/_detail_overview.html:22
+msgid "Flavor"
+msgstr "Flavor"
+
+#: dashboards/admin/flavors/tables.py:23
+#: dashboards/admin/flavors/templates/flavors/_create.html:8
+#: dashboards/admin/flavors/templates/flavors/_create.html:23
+#: dashboards/admin/flavors/templates/flavors/create.html:3
+#: dashboards/admin/flavors/templates/flavors/create.html:6
+msgid "Create Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:30
+#: dashboards/admin/flavors/templates/flavors/_edit.html:8
+#: dashboards/admin/flavors/templates/flavors/edit.html:3
+#: dashboards/admin/flavors/templates/flavors/edit.html:6
+msgid "Edit Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:36
+#, python-format
+msgid "%sMB"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:40
+msgid "Flavor Name"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:43
+#: dashboards/project/instances/templates/instances/_detail_overview.html:24
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: usage/tables.py:22
+msgid "RAM"
+msgstr "RAM"
+
+#: dashboards/admin/flavors/tables.py:45
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+msgid "Root Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:47
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+msgid "Ephemeral Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:49
+msgid "Unable to retrieve flavor list."
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:76
+msgid "Unable to retrieve flavor data."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:17
+#: dashboards/admin/flavors/templates/flavors/_edit.html:17
+#: dashboards/admin/images/templates/images/_update.html:17
+#: dashboards/admin/networks/templates/networks/_create.html:17
+#: dashboards/admin/networks/templates/networks/ports/_create.html:17
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:17
+#: dashboards/admin/projects/tables.py:89
+#: dashboards/admin/projects/workflows.py:74
+#: dashboards/admin/projects/templates/projects/_add_user.html:17
+#: dashboards/admin/projects/templates/projects/_create.html:17
+#: dashboards/admin/projects/templates/projects/_create_user.html:17
+#: dashboards/admin/projects/templates/projects/_quotas.html:16
+#: dashboards/admin/projects/templates/projects/_update.html:17
+#: dashboards/admin/users/templates/users/_create.html:16
+#: dashboards/admin/users/templates/users/_update.html:16
+#: dashboards/project/access_and_security/security_groups/forms.py:38
+#: dashboards/project/access_and_security/security_groups/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:17
+#: dashboards/project/containers/templates/containers/_copy.html:16
+#: dashboards/project/containers/templates/containers/_create.html:16
+#: dashboards/project/containers/templates/containers/_upload.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/_create.html:16
+#: dashboards/project/networks/templates/networks/subnets/_create.html:17
+#: dashboards/project/volumes/forms.py:28
+#: dashboards/project/volumes/forms.py:195
+#: dashboards/project/volumes/tables.py:147
+#: dashboards/project/volumes/templates/volumes/_create.html:18
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:17
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:14
+msgid "Description"
+msgstr "Omschrijving"
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:18
+msgid "From here you can define the sizing of a new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:24
+#: dashboards/admin/flavors/templates/flavors/_edit.html:25
+#: dashboards/admin/images/templates/images/_update.html:24
+#: dashboards/admin/networks/templates/networks/_create.html:24
+#: dashboards/admin/networks/templates/networks/_update.html:23
+#: dashboards/admin/networks/templates/networks/ports/_create.html:24
+#: dashboards/admin/networks/templates/networks/ports/_update.html:28
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:24
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:32
+#: dashboards/admin/projects/templates/projects/_add_user.html:24
+#: dashboards/admin/projects/templates/projects/_create.html:24
+#: dashboards/admin/projects/templates/projects/_create_user.html:24
+#: dashboards/admin/projects/templates/projects/_quotas.html:23
+#: dashboards/admin/projects/templates/projects/_update.html:24
+#: dashboards/admin/users/templates/users/_create.html:23
+#: dashboards/admin/users/templates/users/_update.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:32
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:20
+#: dashboards/project/containers/templates/containers/_copy.html:23
+#: dashboards/project/containers/templates/containers/_create.html:23
+#: dashboards/project/containers/templates/containers/_upload.html:24
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:32
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:24
+#: dashboards/project/instances/templates/instances/_update.html:23
+#: dashboards/project/networks/templates/networks/_create.html:23
+#: dashboards/project/networks/templates/networks/_update.html:23
+#: dashboards/project/networks/templates/networks/subnets/_create.html:24
+#: dashboards/project/networks/templates/networks/subnets/_update.html:32
+#: dashboards/project/volumes/templates/volumes/_attach.html:24
+#: dashboards/project/volumes/templates/volumes/_create.html:56
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:24
+#: dashboards/settings/ec2/templates/ec2/download_form.html:24
+#: dashboards/settings/project/templates/project/_openrc.html:31
+#: dashboards/settings/user/templates/user/_settings.html:24
+msgid "Cancel"
+msgstr "Annuleren"
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:18
+msgid "From here you can alter the sizing of the current flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:19
+msgid ""
+"Note: this will not affect the resources allocated to any existing instances "
+"using this flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:24
+#: dashboards/admin/projects/workflows.py:270
+#: dashboards/settings/user/templates/user/_settings.html:23
+msgid "Save"
+msgstr "Opslaan"
+
+#: dashboards/admin/images/panel.py:29 dashboards/admin/images/tables.py:44
+#: dashboards/admin/images/templates/images/index.html:3
+#: dashboards/admin/images/templates/images/index.html:6
+#: dashboards/project/images_and_snapshots/images/tables.py:47
+#: dashboards/project/images_and_snapshots/images/tables.py:132
+msgid "Images"
+msgstr "Images"
+
+#: dashboards/admin/images/tables.py:40
+#: dashboards/project/images_and_snapshots/images/tables.py:113
+#: dashboards/project/instances/templates/instances/_detail_overview.html:74
+msgid "Image Name"
+msgstr "Naam image"
+
+#: dashboards/admin/images/views.py:55
+msgid "Unable to retrieve image list."
+msgstr ""
+
+#: dashboards/admin/images/templates/images/_update.html:8
+#: dashboards/admin/images/templates/images/_update.html:23
+#: dashboards/admin/images/templates/images/update.html:4
+#: dashboards/admin/images/templates/images/update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:22
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:6
+msgid "Update Image"
+msgstr "Image bijwerken"
+
+#: dashboards/admin/images/templates/images/_update.html:18
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:17
+msgid "From here you can modify different properties of an image."
+msgstr ""
+
+#: dashboards/admin/instances/panel.py:29
+#: dashboards/admin/instances/tables.py:94
+#: dashboards/admin/instances/templates/instances/index.html:3
+#: dashboards/admin/projects/workflows.py:40
+#: dashboards/project/instances/panel.py:25
+#: dashboards/project/instances/tables.py:70
+#: dashboards/project/instances/tables.py:90
+#: dashboards/project/instances/tables.py:107
+#: dashboards/project/instances/tables.py:136
+#: dashboards/project/instances/tables.py:313
+#: dashboards/project/instances/templates/instances/index.html:3
+#: dashboards/project/instances/templates/instances/index.html:6
+msgid "Instances"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:60 usage/tables.py:30
+msgid "Project Name"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:67
+#: dashboards/admin/services/tables.py:40
+msgid "Host"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:71
+#: dashboards/project/instances/tables.py:290
+#: dashboards/project/instances/workflows.py:176 usage/tables.py:57
+msgid "Instance Name"
+msgstr "Naam instance"
+
+#: dashboards/admin/instances/tables.py:72
+#: dashboards/project/access_and_security/floating_ips/tables.py:111
+#: dashboards/project/access_and_security/floating_ips/workflows.py:32
+#: dashboards/project/access_and_security/floating_ips/workflows.py:39
+#: dashboards/project/instances/tables.py:291
+msgid "IP Address"
+msgstr "IP adres"
+
+#: dashboards/admin/instances/tables.py:74
+#: dashboards/project/containers/tables.py:256
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:30
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:37
+#: dashboards/project/instances/tables.py:293
+#: dashboards/project/volumes/tables.py:150
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:26
+msgid "Size"
+msgstr "Grootte"
+
+#: dashboards/admin/instances/tables.py:79
+#: dashboards/admin/networks/tables.py:74
+#: dashboards/admin/networks/ports/tables.py:77
+#: dashboards/project/images_and_snapshots/images/tables.py:119
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:13
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:18
+#: dashboards/project/instances/tables.py:298
+#: dashboards/project/instances/templates/instances/_detail_overview.html:13
+#: dashboards/project/networks/tables.py:100
+#: dashboards/project/networks/ports/tables.py:44
+#: dashboards/project/networks/templates/networks/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:30
+#: dashboards/project/volumes/tables.py:154
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:17
+msgid "Status"
+msgstr "Status"
+
+#: dashboards/admin/instances/tables.py:83
+#: dashboards/project/instances/tables.py:302
+msgid "Task"
+msgstr "Taak"
+
+#: dashboards/admin/instances/tables.py:90
+#: dashboards/project/instances/tables.py:309
+msgid "Power State"
+msgstr ""
+
+#: dashboards/admin/instances/views.py:49
+#: dashboards/project/access_and_security/views.py:76
+#: dashboards/project/access_and_security/floating_ips/workflows.py:65
+msgid "Unable to retrieve instance list."
+msgstr ""
+
+#: dashboards/admin/instances/views.py:63
+#: dashboards/admin/networks/views.py:48
+msgid "Unable to retrieve instance tenant information."
+msgstr ""
+
+#: dashboards/admin/instances/views.py:80
+#: dashboards/project/instances/views.py:82
+msgid "Unable to retrieve instance size information."
+msgstr ""
+
+#: dashboards/admin/instances/templates/instances/index.html:6
+msgid "All Instances"
+msgstr "Alle instances"
+
+#: dashboards/admin/networks/forms.py:36
+#: dashboards/admin/networks/tables.py:67
+#: dashboards/admin/projects/tables.py:65 dashboards/project/dashboard.py:40
+#: dashboards/project/instances/workflows.py:38
+msgid "Project"
+msgstr "Project"
+
+#: dashboards/admin/networks/forms.py:37 dashboards/admin/networks/forms.py:74
+#: dashboards/admin/networks/tables.py:72
+#: dashboards/project/networks/tables.py:98
+#: dashboards/project/networks/templates/networks/_detail_overview.html:17
+msgid "Shared"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:46 dashboards/admin/users/forms.py:42
+msgid "Select a project"
+msgstr "Naam instance"
+
+#: dashboards/admin/networks/forms.py:58
+#, python-format
+msgid "Network %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:64
+#, python-format
+msgid "Failed to create network %s"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:71
+#: dashboards/admin/networks/templates/networks/ports/_update.html:12
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:12
+#: dashboards/admin/users/forms.py:114
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:11
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:12
+#: dashboards/project/instances/templates/instances/_detail_overview.html:11
+#: dashboards/project/networks/forms.py:39
+#: dashboards/project/networks/templates/networks/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_update.html:12
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:11
+msgid "ID"
+msgstr "ID"
+
+#: dashboards/admin/networks/forms.py:82
+#: dashboards/project/networks/forms.py:48
+#, python-format
+msgid "Network %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:87
+#: dashboards/project/networks/forms.py:53
+#, python-format
+msgid "Failed to update network %s"
+msgstr ""
+
+#: dashboards/admin/networks/panel.py:25
+#: dashboards/admin/networks/tables.py:35
+#: dashboards/admin/networks/tables.py:80
+#: dashboards/admin/networks/templates/networks/index.html:3
+#: dashboards/admin/networks/templates/networks/index.html:6
+#: dashboards/project/instances/workflows.py:412
+#: dashboards/project/networks/panel.py:25
+#: dashboards/project/networks/tables.py:44
+#: dashboards/project/networks/tables.py:106
+#: dashboards/project/networks/templates/networks/index.html:3
+#: dashboards/project/networks/templates/networks/index.html:6
+msgid "Networks"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:34
+#: dashboards/project/networks/tables.py:43
+#: dashboards/project/networks/templates/networks/subnets/index.html:3
+#: dashboards/project/networks/templates/networks/subnets/index.html:6
+msgid "Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:41
+#: dashboards/project/networks/tables.py:59
+#, python-format
+msgid "Failed to delete network %s"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:49
+#: dashboards/admin/networks/templates/networks/_create.html:8
+#: dashboards/admin/networks/templates/networks/_create.html:23
+#: dashboards/admin/networks/templates/networks/create.html:3
+#: dashboards/admin/networks/templates/networks/create.html:6
+#: dashboards/project/networks/tables.py:67
+#: dashboards/project/networks/workflows.py:111
+#: dashboards/project/networks/templates/networks/_create.html:7
+#: dashboards/project/networks/templates/networks/_create.html:22
+#: dashboards/project/networks/templates/networks/create.html:3
+#: dashboards/project/networks/templates/networks/create.html:6
+msgid "Create Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:56
+#: dashboards/admin/networks/templates/networks/_update.html:7
+#: dashboards/project/networks/tables.py:74
+#: dashboards/project/networks/templates/networks/_update.html:7
+msgid "Edit Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:68
+#: dashboards/admin/networks/ports/forms.py:33
+#: dashboards/project/networks/subnets/forms.py:35
+msgid "Network Name"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:71
+#: dashboards/project/networks/tables.py:97
+msgid "Subnets Associated"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:76
+#: dashboards/admin/networks/ports/tables.py:79
+#: dashboards/project/networks/tables.py:102
+#: dashboards/project/networks/ports/tables.py:46
+#: dashboards/project/networks/templates/networks/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:32
+msgid "Admin State"
+msgstr ""
+
+#: dashboards/admin/networks/views.py:60
+#: dashboards/project/networks/views.py:52
+msgid "Network list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:91
+#: dashboards/project/networks/views.py:109
+msgid "Subnet list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:103
+#: dashboards/project/networks/views.py:121
+msgid "Port list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:118
+#: dashboards/project/networks/views.py:134
+#: dashboards/project/networks/subnets/tables.py:96
+#, python-format
+msgid "Unable to retrieve details for network \"%s\"."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:36
+#: dashboards/project/networks/subnets/forms.py:39
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:13
+msgid "Network ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:42
+#: dashboards/admin/networks/ports/forms.py:74
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:34
+msgid "Device ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:54
+#, python-format
+msgid "Port %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:59
+#, python-format
+msgid "Failed to create a port for network %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:84
+#, python-format
+msgid "Port %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:89
+#, python-format
+msgid "Failed to update port %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:34
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:6
+msgid "Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:35
+#: dashboards/admin/networks/ports/tables.py:83
+#: dashboards/project/networks/ports/tables.py:53
+msgid "Ports"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:41
+#: dashboards/admin/networks/subnets/tables.py:39
+#: dashboards/project/networks/subnets/tables.py:51
+#, python-format
+msgid "Failed to delete subnet %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:51
+#: dashboards/admin/networks/templates/networks/ports/_create.html:8
+#: dashboards/admin/networks/templates/networks/ports/_create.html:23
+#: dashboards/admin/networks/templates/networks/ports/create.html:3
+#: dashboards/admin/networks/templates/networks/ports/create.html:6
+msgid "Create Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:62
+#: dashboards/admin/networks/templates/networks/ports/_update.html:7
+msgid "Edit Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:75
+#: dashboards/project/networks/ports/tables.py:42
+msgid "Fixed IPs"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:76
+#: dashboards/project/networks/ports/tables.py:43
+msgid "Device Attached"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tabs.py:32
+#: dashboards/admin/overview/panel.py:29
+#: dashboards/admin/overview/templates/overview/usage.html:6
+#: dashboards/project/images_and_snapshots/images/tabs.py:27
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:27
+#: dashboards/project/instances/tabs.py:26
+#: dashboards/project/networks/ports/tabs.py:32
+#: dashboards/project/networks/subnets/tabs.py:32
+#: dashboards/project/overview/panel.py:29
+#: dashboards/project/overview/templates/overview/usage.html:6
+#: dashboards/project/volumes/tabs.py:27
+msgid "Overview"
+msgstr "Overzicht"
+
+#: dashboards/admin/networks/ports/tabs.py:42
+#: dashboards/project/networks/ports/tabs.py:42
+msgid "Unable to retrieve port details."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:49
+#: dashboards/admin/networks/subnets/views.py:49
+#: dashboards/project/networks/subnets/views.py:54
+msgid "Unable to retrieve network."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:82
+msgid "Unable to retrieve port details"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/forms.py:43
+#, python-format
+msgid "Failed to retrieve network %s for a subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:32
+#: dashboards/project/networks/subnets/tables.py:44
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:6
+msgid "Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:33
+#: dashboards/admin/networks/subnets/tables.py:81
+#: dashboards/project/networks/subnets/tables.py:45
+#: dashboards/project/networks/subnets/tables.py:104
+msgid "Subnets"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:49
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:8
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:23
+#: dashboards/admin/networks/templates/networks/subnets/create.html:3
+#: dashboards/admin/networks/templates/networks/subnets/create.html:6
+#: dashboards/project/networks/workflows.py:53
+#: dashboards/project/networks/subnets/tables.py:61
+#: dashboards/project/networks/templates/networks/subnets/_create.html:8
+#: dashboards/project/networks/templates/networks/subnets/_create.html:23
+#: dashboards/project/networks/templates/networks/subnets/create.html:3
+#: dashboards/project/networks/templates/networks/subnets/create.html:6
+msgid "Create Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:60
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:7
+#: dashboards/project/networks/subnets/tables.py:72
+#: dashboards/project/networks/templates/networks/subnets/_update.html:7
+msgid "Edit Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:72
+#: dashboards/project/access_and_security/security_groups/forms.py:91
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:15
+msgid "CIDR"
+msgstr "CIDR"
+
+#: dashboards/admin/networks/subnets/tables.py:73
+#: dashboards/project/networks/workflows.py:66
+#: dashboards/project/networks/subnets/forms.py:53
+#: dashboards/project/networks/subnets/tables.py:85
+msgid "IP Version"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:74
+#: dashboards/project/networks/subnets/forms.py:54
+#: dashboards/project/networks/subnets/forms.py:104
+#: dashboards/project/networks/subnets/tables.py:86
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:19
+msgid "Gateway IP"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/views.py:82
+#: dashboards/project/networks/subnets/views.py:86
+msgid "Unable to retrieve subnet details"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_create.html:18
+#: dashboards/project/networks/templates/networks/_create.html:17
+msgid "Select a name for your network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:16
+#: dashboards/admin/networks/templates/networks/ports/_update.html:21
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:25
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:17
+#: dashboards/project/instances/templates/instances/_update.html:16
+#: dashboards/project/networks/templates/networks/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_update.html:25
+#: dashboards/settings/ec2/templates/ec2/download_form.html:17
+#: dashboards/settings/project/templates/project/_openrc.html:24
+#: dashboards/settings/user/templates/user/_settings.html:17
+msgid "Description:"
+msgstr "Omschrijving:"
+
+#: dashboards/admin/networks/templates/networks/_update.html:17
+#: dashboards/project/networks/templates/networks/_update.html:17
+msgid "You may update the editable properties of your network here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:22
+#: dashboards/admin/networks/templates/networks/ports/_update.html:27
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:31
+#: dashboards/project/instances/templates/instances/_update.html:22
+#: dashboards/project/networks/templates/networks/_update.html:22
+#: dashboards/project/networks/templates/networks/subnets/_update.html:31
+msgid "Save Changes"
+msgstr "Sla bewerkingen op"
+
+#: dashboards/admin/networks/templates/networks/update.html:3
+#: dashboards/admin/networks/templates/networks/update.html:6
+#: dashboards/project/networks/templates/networks/update.html:3
+#: dashboards/project/networks/templates/networks/update.html:6
+msgid "Update Network"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_create.html:18
+msgid ""
+"You can create a port for the network. If you specify device ID to be "
+"attached, the device specified will be attached to the port created."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_update.html:22
+msgid "You may update the editable properties of your port here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/update.html:3
+#: dashboards/admin/networks/templates/networks/ports/update.html:6
+msgid "Update Port"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:18
+#: dashboards/project/networks/templates/networks/subnets/_create.html:18
+msgid ""
+"You can create a subnet for the network. Any network address can be "
+"specified unless the network address does not overlap other subnets in the "
+"network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:14
+#: dashboards/project/networks/workflows.py:58
+#: dashboards/project/networks/subnets/forms.py:45
+#: dashboards/project/networks/subnets/tables.py:84
+#: dashboards/project/networks/templates/networks/subnets/_update.html:14
+msgid "Network Address"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:17
+#: dashboards/project/networks/templates/networks/subnets/_update.html:16
+msgid "IP version"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:26
+#: dashboards/project/networks/templates/networks/subnets/_update.html:26
+msgid "You may update the editable properties of your subnet here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/index.html:3
+#: dashboards/admin/networks/templates/networks/subnets/index.html:6
+#: dashboards/project/networks/templates/networks/detail.html:3
+msgid "Network Detail"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/update.html:3
+#: dashboards/admin/networks/templates/networks/subnets/update.html:6
+#: dashboards/project/networks/templates/networks/subnets/update.html:3
+#: dashboards/project/networks/templates/networks/subnets/update.html:6
+msgid "Update Subnet"
+msgstr ""
+
+#: dashboards/admin/overview/templates/overview/usage.html:3
+msgid "Usage Overview"
+msgstr "Overzicht verbruik"
+
+#: dashboards/admin/overview/templates/overview/usage.html:12
+msgid "Monitoring"
+msgstr "Items"
+
+#: dashboards/admin/projects/panel.py:29
+#: dashboards/admin/projects/tables.py:66
+#: dashboards/admin/projects/tables.py:95
+#: dashboards/admin/projects/templates/projects/index.html:8
+#: templates/403.html:24 templates/404.html:23 templates/500.html:23
+msgid "Projects"
+msgstr "Projecten"
+
+#: dashboards/admin/projects/tables.py:19
+msgid "Modify Users"
+msgstr "Bewerk gebruikers"
+
+#: dashboards/admin/projects/tables.py:32
+msgid "View Usage"
+msgstr "Bekijk verbruik"
+
+#: dashboards/admin/projects/tables.py:39
+#: dashboards/admin/projects/templates/projects/_create.html:8
+#: dashboards/admin/projects/templates/projects/_create.html:23
+#: dashboards/admin/projects/templates/projects/create.html:6
+msgid "Create Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:46
+#: dashboards/admin/projects/workflows.py:269
+#: dashboards/admin/projects/templates/projects/update.html:3
+#: dashboards/admin/projects/templates/projects/update.html:6
+msgid "Edit Project"
+msgstr "Bewerk project"
+
+#: dashboards/admin/projects/tables.py:90
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:60
+#: dashboards/project/networks/templates/networks/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:15
+msgid "Project ID"
+msgstr "Project ID"
+
+#: dashboards/admin/projects/tables.py:91
+#: dashboards/admin/projects/workflows.py:76
+#: dashboards/admin/projects/workflows.py:251
+#: dashboards/admin/services/tables.py:42 dashboards/admin/users/tables.py:40
+#: dashboards/admin/users/tables.py:115
+msgid "Enabled"
+msgstr "Ingeschakeld"
+
+#: dashboards/admin/projects/tables.py:104
+msgid "Remove"
+msgstr "Verwijder"
+
+#: dashboards/admin/projects/tables.py:105
+msgid "Removed"
+msgstr "Verwijderd"
+
+#: dashboards/admin/projects/tables.py:106 dashboards/admin/users/tables.py:41
+#: dashboards/admin/users/tables.py:75
+#: dashboards/project/instances/workflows.py:39
+msgid "User"
+msgstr "Gebruiker"
+
+#: dashboards/admin/projects/tables.py:107 dashboards/admin/users/panel.py:29
+#: dashboards/admin/users/tables.py:42 dashboards/admin/users/tables.py:76
+#: dashboards/admin/users/tables.py:122
+#: dashboards/admin/users/templates/users/index.html:8
+msgid "Users"
+msgstr "Gebruikers"
+
+#: dashboards/admin/projects/tables.py:125
+msgid "Unable to retrieve role information."
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:130
+msgid "Roles"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:134
+msgid "Users For Project"
+msgstr "Gebruikers voor project"
+
+#: dashboards/admin/projects/tables.py:142
+msgid "Add To Project"
+msgstr "Toevoegen aan project"
+
+#: dashboards/admin/projects/tables.py:154
+msgid "Add New Users"
+msgstr "Voeg nieuwe gebruikers toe"
+
+#: dashboards/admin/projects/views.py:67
+msgid "Unable to retrieve project information."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:87
+msgid "Unable to retrieve project list."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:110
+msgid "Unable to retrieve users."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:154
+msgid "Unable to retrieve default quota values."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:182
+msgid "Unable to retrieve project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:37
+msgid "Injected File Content Bytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:38
+msgid "Metadata Items"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:41
+msgid "Injected Files"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:44
+#: dashboards/admin/volumes/panel.py:9 dashboards/admin/volumes/tables.py:15
+#: dashboards/admin/volumes/templates/volumes/index.html:3
+#: dashboards/admin/volumes/templates/volumes/index.html:6
+#: dashboards/project/volumes/panel.py:25
+#: dashboards/project/volumes/tables.py:38
+#: dashboards/project/volumes/tables.py:171
+#: dashboards/project/volumes/tables.py:183
+#: dashboards/project/volumes/templates/volumes/index.html:3
+#: dashboards/project/volumes/templates/volumes/index.html:6
+msgid "Volumes"
+msgstr "Volumes"
+
+#: dashboards/admin/projects/workflows.py:45
+msgid "Gigabytes"
+msgstr "Gigabytes"
+
+#: dashboards/admin/projects/workflows.py:46
+msgid "RAM (MB)"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:47
+#: dashboards/project/access_and_security/floating_ips/tables.py:50
+#: dashboards/project/access_and_security/floating_ips/tables.py:128
+msgid "Floating IPs"
+msgstr "Floating IP's"
+
+#: dashboards/admin/projects/workflows.py:50
+msgid "Quota"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:52
+msgid "From here you can set quotas (max limits) for the project."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:81
+#: dashboards/admin/projects/workflows.py:254
+msgid "Project Info"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:82
+#: dashboards/admin/projects/templates/projects/_create.html:18
+msgid "From here you can create a new project to organize users."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:101
+msgid "Unable to retrieve user list. Please try again later."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:155
+#: dashboards/admin/projects/templates/projects/_update_members.html:16
+msgid "Project Members"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:169
+#: dashboards/admin/users/views.py:47
+msgid "Unable to retrieve user list."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:180
+msgid "Add Project"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:181
+msgid "Finish"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:182
+#, python-format
+msgid "Created new project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:183
+#, python-format
+msgid "Unable to create project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:227
+#, python-format
+msgid "Failed to add %s project members and set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:246
+msgid "Unable to set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:256
+msgid "From here you can edit the project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:271
+#, python-format
+msgid "Modified project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:272
+#, python-format
+msgid "Unable to modify project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:342
+#, python-format
+msgid "Failed to modify %s project members and update project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:363
+msgid ""
+"Modified project information and members, but unable to modify project "
+"quotas."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:8
+#: dashboards/admin/projects/templates/projects/add_user.html:3
+#: dashboards/admin/projects/templates/projects/add_user.html:6
+msgid "Add User To Project"
+msgstr "Voeg gebruiker toe aan project"
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:18
+msgid "Select the user role for the project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:23
+msgid "Add"
+msgstr "Toevoegen"
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:7
+#, python-format
+msgid "Create User for project '%(tenant_name)s'."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:18
+msgid "From here you can create a new user to add to this project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:23
+#: dashboards/admin/users/tables.py:20
+#: dashboards/admin/users/templates/users/_create.html:7
+#: dashboards/admin/users/templates/users/_create.html:22
+#: dashboards/admin/users/templates/users/create.html:7
+msgid "Create User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:7
+#: dashboards/admin/projects/templates/projects/_quotas.html:22
+msgid "Update Quota"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:17
+#, python-format
+msgid ""
+"From here you can edit quotas (max limits) for the project %(tenant.name)s."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update.html:8
+#: dashboards/admin/projects/templates/projects/_update.html:23
+#: dashboards/admin/projects/templates/projects/quotas.html:6
+msgid "Update Project"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update.html:18
+msgid "From here you can edit a project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:7
+msgid ""
+"From here you can add and remove members to this project from the list of "
+"all available users."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:10
+msgid "All Users"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:25
+#: dashboards/admin/projects/templates/projects/_update_members.html:32
+msgid "No users found."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/create_user.html:3
+#: dashboards/admin/projects/templates/projects/create_user.html:6
+msgid "Add New User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:3
+msgid "Project Usage Overview"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:7
+msgid "Project Usage"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/users.html:7
+msgid "Users for Project"
+msgstr ""
+
+#: dashboards/admin/quotas/panel.py:29 dashboards/admin/quotas/tables.py:36
+msgid "Quotas"
+msgstr ""
+
+#: dashboards/admin/quotas/tables.py:28
+msgid "Quota Name"
+msgstr ""
+
+#: dashboards/admin/quotas/tables.py:29
+msgid "Limit"
+msgstr "Limiet"
+
+#: dashboards/admin/quotas/views.py:46
+msgid "Unable to get quota info."
+msgstr ""
+
+#: dashboards/admin/quotas/templates/quotas/index.html:8
+msgid "Default Quotas"
+msgstr ""
+
+#: dashboards/admin/services/panel.py:29
+#: dashboards/admin/services/tables.py:47
+#: dashboards/admin/services/templates/services/index.html:8
+msgid "Services"
+msgstr "Services"
+
+#: dashboards/admin/services/tables.py:37
+msgid "Id"
+msgstr "Id"
+
+#: dashboards/admin/services/tables.py:39
+msgid "Service"
+msgstr "Service"
+
+#: dashboards/admin/users/forms.py:54
+msgid "Passwords do not match."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:62 dashboards/admin/users/forms.py:115
+#: dashboards/admin/users/tables.py:108
+msgid "User Name"
+msgstr "Gebruikersnaam"
+
+#: dashboards/admin/users/forms.py:63 dashboards/admin/users/forms.py:116
+#: dashboards/admin/users/tables.py:109
+msgid "Email"
+msgstr "E-mailadres"
+
+#: dashboards/admin/users/forms.py:65 dashboards/admin/users/forms.py:117
+msgid "Password"
+msgstr "Wachtwoord"
+
+#: dashboards/admin/users/forms.py:70 dashboards/admin/users/forms.py:124
+msgid "Confirm Password"
+msgstr "Bevestig wachtwoord"
+
+#: dashboards/admin/users/forms.py:73 dashboards/admin/users/forms.py:127
+msgid "Primary Project"
+msgstr "Primair project"
+
+#: dashboards/admin/users/forms.py:75
+msgid "Role"
+msgstr "Rol"
+
+#: dashboards/admin/users/forms.py:96
+#, python-format
+msgid "User \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:106
+msgid "Unable to add userto primary project."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:110
+msgid "Unable to create user."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:151
+msgid "name"
+msgstr "naam"
+
+#: dashboards/admin/users/forms.py:151
+msgid "email"
+msgstr "e-mailadres"
+
+#: dashboards/admin/users/forms.py:160
+msgid "primary project"
+msgstr "primair project"
+
+#: dashboards/admin/users/forms.py:173
+#, python-format
+msgid "The user %s has no role defined for"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:181
+msgid "password"
+msgstr "wachtwoord"
+
+#: dashboards/admin/users/forms.py:190
+msgid "User has been updated successfully."
+msgstr "Gebruiker is succesvol bewerkt."
+
+#: dashboards/admin/users/forms.py:194
+#, python-format
+msgid "Unable to update %(attributes)s for the user."
+msgstr ""
+
+#: dashboards/admin/users/tables.py:32
+#: dashboards/project/images_and_snapshots/images/tables.py:68
+msgid "Edit"
+msgstr "Bewerk"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Enable"
+msgstr "Schakel in"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Disable"
+msgstr "Schakel uit"
+
+#: dashboards/admin/users/tables.py:40
+msgid "Disabled"
+msgstr "Uitgeschakeld"
+
+#: dashboards/admin/users/tables.py:63
+msgid "You cannot disable the user you are currently logged in as."
+msgstr ""
+
+#: dashboards/admin/users/tables.py:114
+msgid "User ID"
+msgstr ""
+
+#: dashboards/admin/users/views.py:70
+msgid "Unable to update user."
+msgstr ""
+
+#: dashboards/admin/users/views.py:104
+msgid "Unable to retrieve user roles."
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_create.html:17
+msgid "From here you can create a new user and assign them to a project."
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_update.html:7
+#: dashboards/admin/users/templates/users/_update.html:22
+#: dashboards/admin/users/templates/users/update.html:7
+msgid "Update User"
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_update.html:17
+msgid ""
+"From here you can edit the user's details, including their default project."
+msgstr ""
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:3
+#: dashboards/project/volumes/templates/volumes/detail.html:3
+msgid "Volume Details"
+msgstr ""
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:6
+#: dashboards/project/volumes/templates/volumes/detail.html:6
+msgid "Volume Detail"
+msgstr ""
+
+#: dashboards/project/dashboard.py:24
+msgid "Manage Compute"
+msgstr "Beheer Compute"
+
+#: dashboards/project/dashboard.py:35
+msgid "Object Store"
+msgstr "Object Store"
+
+#: dashboards/project/access_and_security/panel.py:26
+#: dashboards/project/instances/workflows.py:348
+msgid "Access & Security"
+msgstr "Toegang & Beveiliging"
+
+#: dashboards/project/access_and_security/views.py:51
+msgid "Unable to retrieve keypair list."
+msgstr "Niet in staat om de lijst van keypairs op te halen."
+
+#: dashboards/project/access_and_security/views.py:60
+#: dashboards/project/access_and_security/security_groups/views.py:74
+msgid "Unable to retrieve security groups."
+msgstr ""
+
+#: dashboards/project/access_and_security/views.py:69
+#: dashboards/project/access_and_security/floating_ips/workflows.py:49
+msgid "Unable to retrieve floating IP addresses."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:32
+msgid "Pool"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:43
+#, python-format
+msgid "Allocated Floating IP %(ip)s."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:47
+msgid "Unable to allocate Floating IP."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:37
+msgid "Allocate IP To Project"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:47
+msgid "Release"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:48
+msgid "Released"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:49
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:22
+msgid "Floating IP"
+msgstr "Floating IP"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:6
+#: dashboards/project/instances/tables.py:219
+msgid "Associate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:76
+msgid "Disassociate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:90
+#, python-format
+msgid "Successfully disassociated Floating IP: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:94
+msgid "Unable to disassociate floating IP."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:114
+#: dashboards/project/access_and_security/floating_ips/workflows.py:36
+#: dashboards/project/instances/tables.py:69
+#: dashboards/project/instances/tables.py:89
+#: dashboards/project/instances/tables.py:106
+#: dashboards/project/instances/tables.py:135
+#: dashboards/project/volumes/tables.py:206
+msgid "Instance"
+msgstr "Instance"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:117
+msgid "Floating IP Pool"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:65
+msgid "Unable to retrieve floating IP pools."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:68
+msgid "No floating IP pools available."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:40
+msgid "Select the IP address you wish to associate with the selected instance."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:53
+msgid "Select an IP address"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:55
+msgid "No IP addresses available"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:76
+#: dashboards/project/volumes/forms.py:160
+msgid "Select an instance"
+msgstr "Selecteer een instance"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:78
+#: dashboards/project/volumes/forms.py:162
+msgid "No instances available"
+msgstr "Geen instances beschikbaar"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:97
+msgid "Manage Floating IP Associations"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:98
+msgid "Associate"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:99
+#, python-format
+msgid "IP address %s associated."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:100
+#, python-format
+msgid "Unable to associate IP address %s."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:38
+#: dashboards/project/access_and_security/keypairs/forms.py:49
+#: dashboards/project/access_and_security/keypairs/tables.py:52
+msgid "Keypair Name"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:40
+msgid ""
+"Keypair names may only contain letters, numbers, underscores and hyphens."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:51
+msgid "Public Key"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:60
+#, python-format
+msgid "Successfully imported public key: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:65
+msgid "Unable to import keypair."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:30
+#: dashboards/project/instances/tables.py:295
+#: dashboards/project/instances/workflows.py:335
+msgid "Keypair"
+msgstr "Keypair"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:31
+#: dashboards/project/access_and_security/keypairs/tables.py:60
+msgid "Keypairs"
+msgstr "Keypairs"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:39
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html:6
+msgid "Import Keypair"
+msgstr "Importeer keypair"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:46
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html:6
+msgid "Create Keypair"
+msgstr "Creër keypair"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:53
+msgid "Fingerprint"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/views.py:74
+#, python-format
+msgid "Unable to create keypair: %(exc)s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:46
+#, python-format
+msgid "Successfully created security group: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:52
+msgid "Unable to create security group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:57
+#: dashboards/project/access_and_security/security_groups/tables.py:93
+msgid "IP Protocol"
+msgstr "IP Protocol"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:61
+msgid "The protocol which this rule should be applied to."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:65
+#: dashboards/project/access_and_security/security_groups/forms.py:71
+#: dashboards/project/access_and_security/security_groups/tables.py:95
+msgid "From Port"
+msgstr "Van poort"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:66
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP type in the range (-1: 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:72
+#: dashboards/project/images_and_snapshots/images/tables.py:115
+msgid "Type"
+msgstr "Type"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:74
+#: dashboards/project/access_and_security/security_groups/forms.py:80
+#: dashboards/project/access_and_security/security_groups/tables.py:96
+msgid "To Port"
+msgstr "Naar poort"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:75
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP code in the range (-1: 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:81
+msgid "Code"
+msgstr "Code"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:84
+msgid "Source Group"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:86
+msgid ""
+"To specify an allowed IP range, select CIDR. To allow access from all "
+"members of another security group select Source Group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:94
+msgid "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:121
+msgid "The ICMP type is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:124
+msgid "The ICMP code is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:127
+msgid "The ICMP type not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:130
+msgid "The ICMP code not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:134
+msgid "The \"from\" port number is invalid."
+msgstr "Poortnummer \"van\" is niet valide."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:137
+msgid "The \"to\" port number is invalid."
+msgstr "Poortnummer \"naar\" is niet valide."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:140
+msgid ""
+"The \"to\" port number must be greater than or equal to the \"from\" port "
+"number."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:146
+msgid "Either CIDR or Source Group may be specified, but not both."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:168
+#, python-format
+msgid "Successfully added rule: %s"
+msgstr "Regel %s succesvol toegevoegd"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:173
+msgid "Unable to add rule to security group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:31
+msgid "Security Group"
+msgstr "Beveiligingsgroep"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:32
+#: dashboards/project/access_and_security/security_groups/tables.py:66
+#: dashboards/project/instances/workflows.py:340
+#: dashboards/project/instances/templates/instances/_detail_overview.html:49
+msgid "Security Groups"
+msgstr "Beveiligingsgroepen"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:45
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html:6
+msgid "Create Security Group"
+msgstr "Creër beveiligingsgroep"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:52
+msgid "Edit Rules"
+msgstr "Bewerk regels"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:72
+msgid "Rule"
+msgstr "Regel"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:73
+msgid "Rules"
+msgstr "Regels"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:97
+msgid "Source"
+msgstr "Bron"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:107
+msgid "Security Group Rules"
+msgstr "Regels beveiligingsgroep"
+
+#: dashboards/project/access_and_security/security_groups/views.py:60
+msgid "Unable to retrieve security group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/views.py:80
+#, python-format
+msgid "%s (current)"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/index.html:6
+msgid "Access &amp; Security"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:8
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html:3
+msgid "Allocate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:18
+msgid "Allocate a floating IP from a given floating ip pool."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:20
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:19
+msgid "Project Quotas"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:31
+msgid "Allocate IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:17
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:17
+msgid ""
+"Keypairs are ssh credentials which are injected into images when they are "
+"launched. Creating a new key pair registers the public key and downloads the "
+"private key (a .pem file)."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:18
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:18
+msgid "Protect and use the key as you would any normal ssh private key."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:6
+msgid "Download Keypair"
+msgstr "Keypair downloaden"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:11
+#, python-format
+msgid ""
+"The keypair &quot;%(keypair_name)s&quot; should download automatically. If "
+"not use the link below."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:15
+#, python-format
+msgid "Download keypair &quot;%(keypair_name)s&quot;"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:18
+msgid "From here you can create a new security group"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:9
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html:6
+msgid "Edit Security Group Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:12
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:19
+msgid "Add Rule"
+msgstr "Regel toevoegen"
+
+#: dashboards/project/containers/browsers.py:26
+msgid "Swift"
+msgstr ""
+
+#: dashboards/project/containers/browsers.py:29
+#: dashboards/project/containers/tables.py:40
+msgid "Container"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:39
+msgid "Slash is not an allowed character."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:49
+#: dashboards/project/containers/tables.py:121
+msgid "Container Name"
+msgstr "Container naam"
+
+#: dashboards/project/containers/forms.py:57
+msgid "Container created successfully."
+msgstr "Container succesvol aangemaakt."
+
+#: dashboards/project/containers/forms.py:68
+msgid "Folder created successfully."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:71
+msgid "Unable to create container."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:79
+#: dashboards/project/containers/tables.py:253
+msgid "Object Name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:81
+msgid "File"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:95
+msgid "Object was successfully uploaded."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:98
+msgid "Unable to upload object."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:102
+msgid "Destination container"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:106
+msgid "Destination object name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:137
+#: dashboards/project/containers/forms.py:163
+msgid "Unable to copy object."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:153
+#, python-format
+msgid "Copied \"%(orig)s\" to \"%(dest)s\" as \"%(new)s\"."
+msgstr ""
+
+#: dashboards/project/containers/panel.py:29
+#: dashboards/project/containers/tables.py:41
+#: dashboards/project/containers/tables.py:128
+#: dashboards/project/containers/templates/containers/index.html:7
+msgid "Containers"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:62
+#: dashboards/project/containers/templates/containers/_create.html:7
+#: dashboards/project/containers/templates/containers/_create.html:22
+#: dashboards/project/containers/templates/containers/create.html:6
+msgid "Create Container"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:69
+msgid "View Container"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:81
+#: dashboards/project/containers/templates/containers/_upload.html:23
+#: dashboards/project/containers/templates/containers/upload.html:3
+msgid "Upload Object"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:137
+#: dashboards/project/containers/tables.py:156
+msgid "Object"
+msgstr "Object"
+
+#: dashboards/project/containers/tables.py:138
+#: dashboards/project/containers/tables.py:157
+#: dashboards/project/containers/tables.py:263
+msgid "Objects"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:149
+msgid "Folder"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:150
+msgid "Folders"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:163
+msgid "Copy"
+msgstr "Kopieëren "
+
+#: dashboards/project/containers/tables.py:176
+msgid "Download"
+msgstr "Downloaden"
+
+#: dashboards/project/containers/tables.py:232
+msgid "Create Folder"
+msgstr ""
+
+#: dashboards/project/containers/views.py:53
+msgid "Unable to retrieve container list."
+msgstr ""
+
+#: dashboards/project/containers/views.py:82
+msgid "Unable to retrieve object list."
+msgstr ""
+
+#: dashboards/project/containers/views.py:166
+msgid "Unable to retrieve object."
+msgstr ""
+
+#: dashboards/project/containers/views.py:200
+msgid "Unable to list containers."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_copy.html:7
+#: dashboards/project/containers/templates/containers/_copy.html:22
+#: dashboards/project/containers/templates/containers/copy.html:3
+#: dashboards/project/containers/templates/containers/copy.html:6
+msgid "Copy Object"
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_copy.html:17
+msgid ""
+"Make a new copy of an existing object to store in this or another container. "
+"You may also specify a path at which the new copy should live inside of the "
+"selected container."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_create.html:17
+msgid ""
+"A container is a storage compartment for your data and provides a way for "
+"you to organize your data. You can think of a container as a folder in "
+"Windows &reg; or a directory in UNIX &reg;. The primary difference between a "
+"container and these other file system concepts is that containers cannot be "
+"nested. You can, however, create an unlimited number of containers within "
+"your account. Data must be stored in a container so you must have at least "
+"one container defined in your account prior to uploading data."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:8
+msgid "Upload Object To Container"
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:18
+msgid ""
+"An object is the basic storage entity and any optional metadata that "
+"represents the files you store in the OpenStack Object Storage system. When "
+"you upload data to OpenStack Object Storage, the data is stored as-is (no "
+"compression or encryption) and consists of a location (container), the "
+"object's name, and any metadata consisting of key/value pairs."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/upload.html:6
+msgid "Upload Objects"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/panel.py:26
+msgid "Images & Snapshots"
+msgstr "Images & Snapshots"
+
+#: dashboards/project/images_and_snapshots/views.py:63
+msgid "Unable to retrieve images."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:74
+msgid "Unable to retrieve snapshots."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:82
+#: dashboards/project/volumes/forms.py:65
+msgid "Unable to retrieve volume snapshots."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:42
+msgid "Image Location"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:43
+msgid "An external (HTTP) URL to load the image from."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:46
+#: dashboards/project/images_and_snapshots/images/forms.py:130
+#: dashboards/project/images_and_snapshots/images/tables.py:126
+msgid "Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:50
+msgid "AKI - Amazon Kernel Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:53
+msgid "AMI - Amazon Machine Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:56
+msgid "ARI - Amazon Ramdisk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:59
+msgid "ISO - Optical Disk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:61
+msgid "QCOW2 - QEMU Emulator"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:68
+msgid "Minimum Disk (GB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:69
+#: dashboards/project/images_and_snapshots/images/forms.py:76
+msgid ""
+"The minimum disk size required to boot the image. If unspecified, this value "
+"defaults to 0 (no minimum)."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:75
+msgid "Minimum Ram (MB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:82
+#: dashboards/project/images_and_snapshots/images/forms.py:134
+#: dashboards/project/images_and_snapshots/images/tables.py:123
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:15
+msgid "Public"
+msgstr "Publiek"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:106
+#, python-format
+msgid "Your image %s has been queued for creation."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:110
+msgid "Unable to create new image."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:116
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:48
+msgid "Kernel ID"
+msgstr "Kernel ID"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:121
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:52
+msgid "Ramdisk ID"
+msgstr "Ramdisk ID"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:126
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:44
+msgid "Architecture"
+msgstr "Architectuur"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:138
+#, python-format
+msgid "Unable to update image \"%s\"."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:162
+msgid "Image was successfully updated."
+msgstr "Image is succesvol bijgewerkt."
+
+#: dashboards/project/images_and_snapshots/images/tables.py:34
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:33
+#: dashboards/project/instances/workflows.py:455
+msgid "Launch"
+msgstr "Lanceer"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:46
+#: dashboards/project/images_and_snapshots/images/tables.py:82
+#: dashboards/project/instances/workflows.py:168
+#: dashboards/project/instances/workflows.py:173
+msgid "Image"
+msgstr "Image"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:61
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:31
+msgid "Create Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tabs.py:38
+msgid "Unable to retrieve image details."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/views.py:61
+msgid "Unable to retrieve image."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:37
+msgid "Instance ID"
+msgstr "Instance ID"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:40
+#: dashboards/project/volumes/forms.py:193
+msgid "Snapshot Name"
+msgstr "Naam snapshot"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:50
+#, python-format
+msgid "Snapshot \"%(name)s\" created for instance \"%(inst)s\""
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:56
+msgid "Unable to create snapshot."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:48
+#: dashboards/project/instances/workflows.py:107
+#: dashboards/project/instances/workflows.py:169
+msgid "Snapshot"
+msgstr "Snapshot"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:49
+msgid "Snapshots"
+msgstr "Snapshots"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:55
+msgid "Instance Snapshots"
+msgstr "Instance snapshots"
+
+#: dashboards/project/images_and_snapshots/snapshots/views.py:53
+msgid "Unable to retrieve instance."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:6
+msgid "Images &amp; Snapshots"
+msgstr "Images &amp; Snapshots"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:6
+msgid "Create An Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:18
+msgid "Specify an image to upload to the Image Service."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:21
+msgid ""
+"Currently only images available via an HTTP URL are supported. The image "
+"location must be accessible to the Image Service. Compressed image binaries "
+"are supported (.zip and .tar.gz.)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:24
+msgid "Please note: "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:25
+msgid ""
+"The Image Location field MUST be a valid and direct URL to the image binary. "
+"URLs that redirect or serve error pages will result in unusable images."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:3
+msgid "Image Overview"
+msgstr "Overzicht images"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:6
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:7
+#: dashboards/project/instances/templates/instances/_detail_overview.html:6
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:6
+msgid "Info"
+msgstr "Informatie"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:17
+msgid "Checksum"
+msgstr "Checksum"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:19
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:39
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:28
+msgid "Created"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:21
+msgid "Updated"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:27
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:34
+#: dashboards/project/instances/templates/instances/_detail_overview.html:19
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:23
+msgid "Specs"
+msgstr "Specificaties"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:32
+msgid "Container Format"
+msgstr "Container formaat"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:34
+msgid "Disk Format"
+msgstr "Disk formaat"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:40
+msgid "Custom Properties"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:56
+msgid "Euca2ools state"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:64
+msgid "Image Type"
+msgstr "Type image"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html:4
+msgid "Image Detail "
+msgstr "Details image"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:8
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:3
+#: dashboards/project/instances/tables.py:179
+#: dashboards/project/volumes/tables.py:76
+msgid "Create Snapshot"
+msgstr "Creër snapshot"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:18
+msgid "Snapshots preserve the disk state of a running instance."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:20
+#: dashboards/project/instances/workflows.py:75
+#: dashboards/project/instances/workflows.py:110
+#: dashboards/project/instances/templates/instances/_detail_overview.html:93
+#: dashboards/project/volumes/tables.py:37
+#: dashboards/project/volumes/tables.py:182
+msgid "Volume"
+msgstr "Volume"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:38
+#: dashboards/project/instances/templates/instances/_detail_overview.html:29
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:27
+msgid "GB"
+msgstr "GB"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:6
+msgid "Create a Snapshot"
+msgstr "Creër een snapshot"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:3
+msgid "Volume Snapshot Details"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:6
+msgid "Volume Snapshot Detail"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:34
+#: dashboards/project/instances/workflows.py:76
+msgid "Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:35
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:85
+msgid "Volume Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:43
+#: dashboards/project/volumes/tables.py:59
+#: dashboards/project/volumes/templates/volumes/_create.html:8
+#: dashboards/project/volumes/templates/volumes/_create.html:55
+msgid "Create Volume"
+msgstr "Creër volume"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:80
+#: dashboards/project/volumes/forms.py:26
+msgid "Volume Name"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:41
+#, fuzzy
+msgid "Unable to retrieve snapshot details."
+msgstr "Niet in staat om de lijst van keypairs op te halen."
+
+#: dashboards/project/instances/forms.py:45
+#, python-format
+msgid "Instance \"%s\" updated."
+msgstr ""
+
+#: dashboards/project/instances/forms.py:50
+msgid "Unable to update instance."
+msgstr ""
+
+#: dashboards/project/instances/tables.py:67
+msgid "Terminate"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:68
+msgid "Scheduled termination of"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:87
+msgid "Reboot"
+msgstr "Opnieuw starten"
+
+#: dashboards/project/instances/tables.py:88
+msgid "Rebooted"
+msgstr "Opnieuw gestart"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Pause"
+msgstr "Pauzeren"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Unpause"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:105
+msgid "Paused"
+msgstr "Gepauzeerd"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Unpaused"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:133
+msgid "Suspend"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:133
+msgid "Resume"
+msgstr "Hervatten"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Suspended"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:134
+msgid "Resumed"
+msgstr "Hervat"
+
+#: dashboards/project/instances/tables.py:162
+#: dashboards/project/instances/workflows.py:454
+#: dashboards/project/instances/templates/instances/launch.html:3
+#: dashboards/project/instances/templates/instances/launch.html:6
+msgid "Launch Instance"
+msgstr "Lanceer instance"
+
+#: dashboards/project/instances/tables.py:169
+#: dashboards/project/instances/templates/instances/_update.html:7
+msgid "Edit Instance"
+msgstr "Bewerk instance"
+
+#: dashboards/project/instances/tables.py:189
+msgid "VNC Console"
+msgstr "VNC console"
+
+#: dashboards/project/instances/tables.py:204
+msgid "View Log"
+msgstr "Bekijk log"
+
+#: dashboards/project/instances/tables.py:252
+#, python-format
+msgid "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disk"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:259
+#: dashboards/project/instances/tables.py:266
+msgid "Not available"
+msgstr "Niet beschikbaar"
+
+#: dashboards/project/instances/tabs.py:36
+msgid "Log"
+msgstr "Log"
+
+#: dashboards/project/instances/tabs.py:48
+#: dashboards/project/instances/views.py:106
+#, python-format
+msgid "Unable to get log for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:55
+msgid "VNC"
+msgstr "VNC"
+
+#: dashboards/project/instances/tabs.py:70
+#: dashboards/project/instances/views.py:122
+#, python-format
+msgid "Unable to get VNC console for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/views.py:59
+msgid "Unable to retrieve instances."
+msgstr ""
+
+#: dashboards/project/instances/views.py:144
+msgid "Unable to retrieve instance details."
+msgstr ""
+
+#: dashboards/project/instances/views.py:179
+#, python-format
+msgid "Unable to retrieve details for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:53
+msgid "Project & User"
+msgstr "Project & Gebruiker"
+
+#: dashboards/project/instances/workflows.py:66
+msgid "Don't boot from a volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:67
+msgid "Boot from volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:68
+msgid "Boot from volume snapshot (creates a new volume)."
+msgstr "Acties"
+
+#: dashboards/project/instances/workflows.py:72
+#: dashboards/project/instances/workflows.py:90
+msgid "Volume Options"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:78
+#: dashboards/project/volumes/forms.py:126
+msgid "Device Name"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:81
+msgid "Volume mount point (e.g. 'vda' mounts at '/dev/vda')."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:83
+msgid "Delete on Terminate"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:86
+msgid "Delete volume on instance terminate"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:100
+#, python-format
+msgid "Please choose a volume, or select %s."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:117
+msgid "Select Volume"
+msgstr "Selecteer volume"
+
+#: dashboards/project/instances/workflows.py:125
+msgid "Unable to retrieve list of volumes."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:129
+msgid "Select Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:138
+msgid "Unable to retrieve list of volume snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:171
+msgid "Instance Source"
+msgstr "Bron instantie"
+
+#: dashboards/project/instances/workflows.py:174
+msgid "Instance Snapshot"
+msgstr "Momentopname instantie"
+
+#: dashboards/project/instances/workflows.py:178
+msgid "Size of image to launch."
+msgstr "Grootte van de te lanceren image."
+
+#: dashboards/project/instances/workflows.py:179
+msgid "Instance Count"
+msgstr "Aantal instances"
+
+#: dashboards/project/instances/workflows.py:182
+msgid "Number of instances to launch."
+msgstr "Aantal te lanceren instances."
+
+#: dashboards/project/instances/workflows.py:185
+msgid "Details"
+msgstr "Details"
+
+#: dashboards/project/instances/workflows.py:198
+msgid ""
+"There are no image sources available; you must first create an image before "
+"attempting to launch an instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:203
+msgid "Please select an option for the instance source."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:212
+msgid ""
+"Launching multiple instances is only supported for images and instance "
+"snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:229
+msgid "Unable to retrieve public images."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:244
+msgid "Unable to retrieve images for the current project."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:267
+msgid "Select Image"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:269
+msgid "No images available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:278
+msgid "Select Instance Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:280
+msgid "No snapshots available."
+msgstr "Geen momentopname beschikbaar."
+
+#: dashboards/project/instances/workflows.py:291
+msgid "Unable to retrieve instance flavors."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:304 usage/base.py:114
+msgid "Unable to retrieve quota information."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:337
+msgid "Which keypair to use for authentication."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:344
+msgid "Launch instance in these security groups."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:349
+msgid ""
+"Control access to your instance via keypairs, security groups, and other "
+"mechanisms."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:359
+msgid "Unable to retrieve keypairs."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:361
+msgid "Select a keypair"
+msgstr "Selecteer een keypair"
+
+#: dashboards/project/instances/workflows.py:363
+msgid "No keypairs available."
+msgstr "Geen keypairs beschikbaar."
+
+#: dashboards/project/instances/workflows.py:372
+msgid "Unable to retrieve list of security groups"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:392
+msgid "Customization Script"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:394
+msgid ""
+"A script or set of commands to be executed after the instance has been built "
+"(max 16kb)."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:401
+msgid "Post-Creation"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:415
+msgid "Launch instance withthese networks"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:419
+msgid "Networking"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:421
+msgid "Select networks for your instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:433
+msgid "Unable to retrieve networks."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:456
+#, python-format
+msgid "Launched %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:457
+#, python-format
+msgid "Unable to launch %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:470
+#, python-format
+msgid "%s instances"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:473
+msgid "instance"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:4
+msgid "Instance Console Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:7
+msgid "Log Length"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:9
+msgid "Go"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:11
+msgid "View Full Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:3
+msgid "Instance Overview"
+msgstr "Overzicht instances"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:27
+msgid "VCPU"
+msgstr "VCPU"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:28
+#: usage/tables.py:20
+msgid "Disk"
+msgstr "Disk"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:34
+msgid "IP Addresses"
+msgstr "IP adressen"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:59
+msgid "No rules defined."
+msgstr "Geen regels gedefinieërd."
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:68
+msgid "Meta"
+msgstr "Meta"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:71
+msgid "Key Name"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:84
+msgid "Volumes Attached"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:88
+#: dashboards/project/volumes/tables.py:167
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:38
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:45
+msgid "Attached To"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:90
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:42
+msgid "on"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:94
+msgid "No volumes attached."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:3
+msgid "Instance VNC Console"
+msgstr "Instance snapshots"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid ""
+"If VNC console is not responding to keyboard input: click the grey status "
+"bar below."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid "Click here to show only VNC"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:8
+msgid "VNC console is currently unavailabe. Please try again later."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:9
+msgid "Reload"
+msgstr "Herlaad"
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:2
+msgid ""
+"You can customize your instance after it's launched using the options "
+"available here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:3
+msgid ""
+"The \"Customization Script\" field is analogous to \"User Data\" in other "
+"systems."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:3
+msgid "Specify the details for launching an instance."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:4
+msgid ""
+"The chart below shows the resources used by this project in relation to the "
+"project's quotas."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:6
+msgid "Flavor Details"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+msgid "Total Disk"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "MB"
+msgstr "MB"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:21
+msgid "Number of Instances"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:29
+msgid "Number of VCPUs"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "Total RAM"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_volumes_help.html:3
+msgid ""
+"An instance can be launched with varying types of attached storage. You may "
+"select from those options here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_update.html:17
+msgid "You may update the editable properties of your instance here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/detail.html:3
+msgid "Instance Detail"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/update.html:3
+#: dashboards/project/instances/templates/instances/update.html:6
+msgid "Update Instance"
+msgstr ""
+
+#: dashboards/project/networks/tables.py:81
+msgid "Add Subnet"
+msgstr ""
+
+#: dashboards/project/networks/views.py:86
+msgid "Unable to retrieve network details."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:37
+msgid "Network Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:42
+msgid ""
+"From here you can create a new network.\n"
+"In addition a subnet associated with the network can be created in the next "
+"panel."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:56
+msgid "Subnet Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:61
+#: dashboards/project/networks/subnets/forms.py:48
+msgid "Network address in CIDR format (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:67
+msgid "Gateway IP (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:70
+#: dashboards/project/networks/subnets/forms.py:57
+#: dashboards/project/networks/subnets/forms.py:107
+msgid "IP address of Gateway (e.g. 192.168.0.1)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:77
+msgid ""
+"You can create a subnet associated with the new network, in which case "
+"\"Network Address\" must be specified. If you wish to create a network "
+"WITHOUT a subnet, uncheck the \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:89
+msgid "Specify \"Network Address\" or clear \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:94
+#: dashboards/project/networks/subnets/forms.py:70
+msgid "Network Address and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:98
+#: dashboards/project/networks/subnets/forms.py:74
+#: dashboards/project/networks/subnets/forms.py:119
+msgid "Gateway IP and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:112
+msgid "Create"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:113
+#, python-format
+msgid "Created network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:114
+#, python-format
+msgid "Unable to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:130
+#, python-format
+msgid "Network \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:133
+#, python-format
+msgid "Failed to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:152
+#, python-format
+msgid "Subnet \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:155
+#, python-format
+msgid "Failed to create subnet \"%(sub)s\" for network \"%(net)s\"."
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Attached"
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Detached"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:85
+#, python-format
+msgid "Subnet %s was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:90
+#, python-format
+msgid "Failed to create subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:131
+#, python-format
+msgid "Subnet %s was successfully updated."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:136
+#, python-format
+msgid "Failed to update subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/tabs.py:42
+msgid "Unable to retrieve subnet details."
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/_detail_overview.html:3
+msgid "Network Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/detail.html:6
+msgid "Network Detail: "
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:3
+msgid "Port Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:17
+msgid "Fixed IP"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:21
+msgid "IP address:"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:22
+msgid "Subnet ID"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:28
+msgid "Mac Address"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/detail.html:3
+#: dashboards/project/networks/templates/networks/ports/detail.html:6
+msgid "Port Detail"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:3
+msgid "Subnet Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:21
+msgid "IP allocation pool"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:24
+msgid "Start"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:25
+msgid " - End"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/detail.html:3
+#: dashboards/project/networks/templates/networks/subnets/detail.html:6
+msgid "Subnet Detail"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:29
+msgid "Size (GB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:30
+msgid "Use snapshot as a source"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:49
+#, python-format
+msgid "Volume size must be equal to or greater than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:54
+msgid "Unable to load the specified snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:59
+msgid "Choose a snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:83
+#, python-format
+msgid "The volume size cannot be less than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:92
+#, python-format
+msgid ""
+"A volume of %(req)iGB cannot be created as you only have %(avail)iGB of your "
+"quota available."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:99
+msgid "You are already using all of your available volumes."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:115
+msgid "Unable to create volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:123
+msgid "Attach to Instance"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:124
+msgid "Select an instance to attach to."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:168
+msgid "Unknown instance (None)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:179
+#, python-format
+msgid "Attaching volume %(vol)s to instance %(inst)s on %(dev)s."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:188
+msgid "Unable to attach volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:212
+#, python-format
+msgid "Creating volume snapshot \"%s\""
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:218
+msgid "Unable to create volume snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:46
+#, python-format
+msgid "Unable to delete volume \"%s\". One or more snapshots depend on it."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:66
+msgid "Edit Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:93
+#, python-format
+msgid "%sGB"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:106
+#: dashboards/project/volumes/views.py:149
+msgid "Unable to retrieve attachment information."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:123
+#, python-format
+msgid "Attached to %(instance)s on %(dev)s"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:180
+msgid "Detach"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:181
+msgid "Detaching"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:216
+#, python-format
+msgid "%(dev)s on instance %(instance_name)s"
+msgstr ""
+
+#: dashboards/project/volumes/tabs.py:42
+msgid "Unable to retrieve volume details."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:50
+msgid "Unable to retrieve volume list."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:58
+msgid "Unable to retrieve volume/instance attachment information"
+msgstr ""
+
+#: dashboards/project/volumes/views.py:130
+#: dashboards/project/volumes/views.py:140
+msgid "Unable to retrieve volume information."
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:9
+#: dashboards/project/volumes/templates/volumes/attach.html:6
+msgid "Manage Volume Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:13
+msgid "Attach To Instance"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:22
+msgid "Attach Volume"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:20
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:18
+msgid "Volumes are block devices that can be attached to instances."
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:22
+msgid "Volume Quotas"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:25
+msgid "Total Gigabytes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:34
+msgid "Number of Volumes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:8
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:23
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:3
+msgid "Create Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:3
+msgid "Volume Overview"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:34
+msgid "Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:46
+msgid "Not attached"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/create.html:6
+msgid "Create a Volume"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:6
+msgid "Create a Volume Snapshot"
+msgstr ""
+
+#: dashboards/settings/dashboard.py:24 templates/_header.html:4
+msgid "Settings"
+msgstr "Instellingen"
+
+#: dashboards/settings/ec2/forms.py:36 dashboards/settings/project/forms.py:36
+msgid "Select a Project"
+msgstr "Selecteer een project"
+
+#: dashboards/settings/ec2/forms.py:46
+msgid "Unable to retrieve tenant list."
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:88
+msgid "Unable to fetch EC2 credentials."
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:101
+#, python-format
+msgid "Error writing zipfile: %(exc)s"
+msgstr ""
+
+#: dashboards/settings/ec2/panel.py:25
+msgid "EC2 Credentials"
+msgstr ""
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:8
+#: dashboards/settings/ec2/templates/ec2/download_form.html:23
+#: dashboards/settings/ec2/templates/ec2/index.html:3
+#: dashboards/settings/ec2/templates/ec2/index.html:6
+msgid "Download EC2 Credentials"
+msgstr ""
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:18
+msgid ""
+"Clicking \"Download EC2 Credentials\" will download a zip file which "
+"includes an rc file with your access/secret keys, as well as your x509 "
+"private key and certificate."
+msgstr ""
+
+#: dashboards/settings/project/forms.py:71
+#, python-format
+msgid "Error Downloading RC File: %s"
+msgstr ""
+
+#: dashboards/settings/project/panel.py:25
+#: dashboards/settings/project/templates/project/_openrc.html:8
+#: dashboards/settings/project/templates/project/settings.html:3
+#: dashboards/settings/project/templates/project/settings.html:6
+msgid "OpenStack API"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:27
+msgid "Service Name"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:29
+msgid "Service Endpoint"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:33
+msgid "API Endpoints"
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:15
+msgid "Download OpenStack RC File"
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:25
+msgid ""
+"Download the RC file for the selected project, then type \"source openrc\" "
+"in the terminal to configure your environment to communicate with OpenStack."
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:30
+msgid "Download RC File"
+msgstr ""
+
+#: dashboards/settings/user/forms.py:57
+msgid "Settings saved."
+msgstr ""
+
+#: dashboards/settings/user/panel.py:25
+#: dashboards/settings/user/templates/user/_settings.html:8
+#: dashboards/settings/user/templates/user/settings.html:3
+#: dashboards/settings/user/templates/user/settings.html:6
+msgid "User Settings"
+msgstr "Instellingen gebruiker"
+
+#: dashboards/settings/user/templates/user/_settings.html:18
+msgid "From here you can modify dashboard settings for your user."
+msgstr ""
+
#: templates/403.html:4 templates/403.html.py:9
msgid "Forbidden"
msgstr "Verboden"
@@ -83,10 +3233,6 @@ msgstr "Verboden"
msgid "Home"
msgstr "Thuis"
-#: templates/403.html:24 templates/404.html:23 templates/500.html:23
-msgid "Projects"
-msgstr "Projecten"
-
#: templates/404.html:4
msgid "Page Not Found"
msgstr "Pagina niet gevonden"
@@ -110,3 +3256,47 @@ msgid ""
msgstr ""
"Er is een onverwachte fout opgetreden tijdens het verwerken van je verzoek. "
"Probeer je verzoek nogmaals in te dienen."
+
+#: templates/_header.html:3
+msgid "Logged in as"
+msgstr ""
+
+#: templates/_header.html:6
+msgid "Help"
+msgstr ""
+
+#: templates/_header.html:8
+msgid "Sign Out"
+msgstr ""
+
+#: test/settings.py:50
+msgid "Password must be between 8 and 18 characters."
+msgstr ""
+
+#: usage/base.py:97
+msgid "Unable to retrieve usage information."
+msgstr ""
+
+#: usage/base.py:100
+msgid "You are viewing data for the future, which may or may not exist."
+msgstr ""
+
+#: usage/tables.py:11
+msgid "Download CSV Summary"
+msgstr ""
+
+#: usage/tables.py:25
+msgid "VCPU Hours"
+msgstr "VCPU uren"
+
+#: usage/tables.py:32
+msgid "Disk GB Hours"
+msgstr ""
+
+#: usage/tables.py:40 usage/tables.py:68
+msgid "Usage Summary"
+msgstr ""
+
+#: usage/tables.py:60
+msgid "Uptime"
+msgstr "Uptime"
diff --git a/openstack_dashboard/locale/pl/LC_MESSAGES/django.mo b/openstack_dashboard/locale/pl/LC_MESSAGES/django.mo
index 7ad06bd47..7cd0e710b 100644
--- a/openstack_dashboard/locale/pl/LC_MESSAGES/django.mo
+++ b/openstack_dashboard/locale/pl/LC_MESSAGES/django.mo
Binary files differ
diff --git a/openstack_dashboard/locale/pl/LC_MESSAGES/django.po b/openstack_dashboard/locale/pl/LC_MESSAGES/django.po
index d38b96836..87e0d81bc 100644
--- a/openstack_dashboard/locale/pl/LC_MESSAGES/django.po
+++ b/openstack_dashboard/locale/pl/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-09-18 22:18+0000\n"
+"POT-Creation-Date: 2012-10-05 19:30+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -19,72 +19,3452 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2)\n"
-#: settings.py:141
+#: settings.py:142
msgid "Bulgarian (Bulgaria)"
msgstr ""
-#: settings.py:142
+#: settings.py:143
msgid "Czech"
msgstr ""
-#: settings.py:143
+#: settings.py:144
msgid "English"
msgstr ""
-#: settings.py:144
+#: settings.py:145
msgid "Spanish"
msgstr ""
-#: settings.py:145
+#: settings.py:146
msgid "French"
msgstr ""
-#: settings.py:146
+#: settings.py:147
msgid "Italiano"
msgstr ""
-#: settings.py:147
+#: settings.py:148
msgid "Japanese"
msgstr ""
-#: settings.py:148
+#: settings.py:149
msgid "Korean (Korea)"
msgstr ""
-#: settings.py:149
+#: settings.py:150
msgid "Dutch (Netherlands)"
msgstr ""
-#: settings.py:150
+#: settings.py:151
msgid "Polish"
msgstr ""
-#: settings.py:151
+#: settings.py:152
msgid "Portuguese"
msgstr ""
-#: settings.py:152
+#: settings.py:153
msgid "Portuguese (Brazil)"
msgstr ""
-#: settings.py:153
+#: settings.py:154
msgid "Simplified Chinese"
msgstr ""
-#: settings.py:154
+#: settings.py:155
msgid "Traditional Chinese"
msgstr ""
-#: templates/403.html:4 templates/403.html.py:9
-msgid "Forbidden"
+#: api/keystone.py:56
+#, python-format
+msgid "%(type)s (%(backend)s backend)"
msgstr ""
-#: templates/403.html:20 templates/404.html:19 templates/500.html:19
-msgid "Home"
+#: api/nova.py:191
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(group)s"
+msgstr ""
+
+#: api/nova.py:196
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(cidr)s"
+msgstr ""
+
+#: api/nova.py:532
+msgid "Unknown instance"
+msgstr ""
+
+#: api/swift.py:217
+msgid "Unicode is not currently supported for object copy."
+msgstr ""
+
+#: dashboards/admin/dashboard.py:24
+msgid "System Panel"
+msgstr ""
+
+#: dashboards/admin/dashboard.py:30
+msgid "Admin"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:36 dashboards/admin/networks/forms.py:34
+#: dashboards/admin/networks/forms.py:69
+#: dashboards/admin/networks/ports/forms.py:40
+#: dashboards/admin/networks/ports/forms.py:72
+#: dashboards/admin/networks/ports/tables.py:73
+#: dashboards/admin/networks/subnets/tables.py:70
+#: dashboards/admin/projects/tables.py:87
+#: dashboards/admin/projects/workflows.py:71
+#: dashboards/admin/services/tables.py:38
+#: dashboards/admin/volumes/tables.py:10
+#: dashboards/project/access_and_security/security_groups/forms.py:36
+#: dashboards/project/access_and_security/security_groups/tables.py:58
+#: dashboards/project/images_and_snapshots/images/forms.py:40
+#: dashboards/project/images_and_snapshots/images/forms.py:115
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:9
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:10
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:77
+#: dashboards/project/instances/templates/instances/_detail_overview.html:9
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:9
+#: dashboards/project/networks/forms.py:37
+#: dashboards/project/networks/tables.py:94
+#: dashboards/project/networks/ports/tables.py:40
+#: dashboards/project/networks/subnets/forms.py:43
+#: dashboards/project/networks/subnets/forms.py:102
+#: dashboards/project/networks/subnets/tables.py:82
+#: dashboards/project/networks/templates/networks/_detail_overview.html:7
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:9
+#: dashboards/project/volumes/tables.py:144
+#: dashboards/project/volumes/tables.py:164
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:9
+msgid "Name"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:37 dashboards/admin/flavors/tables.py:41
+#: dashboards/admin/projects/workflows.py:39
+#: dashboards/project/instances/templates/instances/_detail_overview.html:26
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:10
+#: usage/tables.py:19
+msgid "VCPUs"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:38
+msgid "RAM MB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:39
+msgid "Root Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:40
+msgid "Ephemeral Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:50
+#, fuzzy
+msgid "Unable to get unique ID for new flavor."
+msgstr "Nie można ustawić widoczności obrazu na publiczną: %s"
+
+#: dashboards/admin/flavors/forms.py:67
+#, fuzzy, python-format
+msgid "Created flavor \"%s\"."
+msgstr "Utwórz nowy wolumen."
+
+#: dashboards/admin/flavors/forms.py:71
+#, fuzzy
+msgid "Unable to create flavor."
+msgstr "Nie można utworzyć wolumenu: %s"
+
+#: dashboards/admin/flavors/forms.py:92
+#, python-format
+msgid "Updated flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:96
+#, fuzzy
+msgid "Unable to update flavor."
+msgstr "Nie można utworzyć wolumenu: %s"
+
+#: dashboards/admin/flavors/panel.py:29 dashboards/admin/flavors/tables.py:15
+#: dashboards/admin/flavors/tables.py:52
+#: dashboards/admin/flavors/templates/flavors/index.html:3
+#: dashboards/admin/flavors/templates/flavors/index.html:6
+msgid "Flavors"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:14
+#: dashboards/project/instances/workflows.py:177
+#: dashboards/project/instances/templates/instances/_detail_overview.html:22
+msgid "Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:23
+#: dashboards/admin/flavors/templates/flavors/_create.html:8
+#: dashboards/admin/flavors/templates/flavors/_create.html:23
+#: dashboards/admin/flavors/templates/flavors/create.html:3
+#: dashboards/admin/flavors/templates/flavors/create.html:6
+msgid "Create Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:30
+#: dashboards/admin/flavors/templates/flavors/_edit.html:8
+#: dashboards/admin/flavors/templates/flavors/edit.html:3
+#: dashboards/admin/flavors/templates/flavors/edit.html:6
+#, fuzzy
+msgid "Edit Flavor"
+msgstr "Usuń projekt"
+
+#: dashboards/admin/flavors/tables.py:36
+#, python-format
+msgid "%sMB"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:40
+msgid "Flavor Name"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:43
+#: dashboards/project/instances/templates/instances/_detail_overview.html:24
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: usage/tables.py:22
+msgid "RAM"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:45
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+msgid "Root Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:47
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+msgid "Ephemeral Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:49
+#, fuzzy
+msgid "Unable to retrieve flavor list."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/admin/flavors/views.py:76
+#, fuzzy
+msgid "Unable to retrieve flavor data."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:17
+#: dashboards/admin/flavors/templates/flavors/_edit.html:17
+#: dashboards/admin/images/templates/images/_update.html:17
+#: dashboards/admin/networks/templates/networks/_create.html:17
+#: dashboards/admin/networks/templates/networks/ports/_create.html:17
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:17
+#: dashboards/admin/projects/tables.py:89
+#: dashboards/admin/projects/workflows.py:74
+#: dashboards/admin/projects/templates/projects/_add_user.html:17
+#: dashboards/admin/projects/templates/projects/_create.html:17
+#: dashboards/admin/projects/templates/projects/_create_user.html:17
+#: dashboards/admin/projects/templates/projects/_quotas.html:16
+#: dashboards/admin/projects/templates/projects/_update.html:17
+#: dashboards/admin/users/templates/users/_create.html:16
+#: dashboards/admin/users/templates/users/_update.html:16
+#: dashboards/project/access_and_security/security_groups/forms.py:38
+#: dashboards/project/access_and_security/security_groups/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:17
+#: dashboards/project/containers/templates/containers/_copy.html:16
+#: dashboards/project/containers/templates/containers/_create.html:16
+#: dashboards/project/containers/templates/containers/_upload.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/_create.html:16
+#: dashboards/project/networks/templates/networks/subnets/_create.html:17
+#: dashboards/project/volumes/forms.py:28
+#: dashboards/project/volumes/forms.py:195
+#: dashboards/project/volumes/tables.py:147
+#: dashboards/project/volumes/templates/volumes/_create.html:18
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:17
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:14
+msgid "Description"
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:18
+#, fuzzy
+msgid "From here you can define the sizing of a new flavor."
+msgstr "Tutaj można zarządzać użytkownikami i rolami."
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:24
+#: dashboards/admin/flavors/templates/flavors/_edit.html:25
+#: dashboards/admin/images/templates/images/_update.html:24
+#: dashboards/admin/networks/templates/networks/_create.html:24
+#: dashboards/admin/networks/templates/networks/_update.html:23
+#: dashboards/admin/networks/templates/networks/ports/_create.html:24
+#: dashboards/admin/networks/templates/networks/ports/_update.html:28
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:24
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:32
+#: dashboards/admin/projects/templates/projects/_add_user.html:24
+#: dashboards/admin/projects/templates/projects/_create.html:24
+#: dashboards/admin/projects/templates/projects/_create_user.html:24
+#: dashboards/admin/projects/templates/projects/_quotas.html:23
+#: dashboards/admin/projects/templates/projects/_update.html:24
+#: dashboards/admin/users/templates/users/_create.html:23
+#: dashboards/admin/users/templates/users/_update.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:32
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:20
+#: dashboards/project/containers/templates/containers/_copy.html:23
+#: dashboards/project/containers/templates/containers/_create.html:23
+#: dashboards/project/containers/templates/containers/_upload.html:24
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:32
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:24
+#: dashboards/project/instances/templates/instances/_update.html:23
+#: dashboards/project/networks/templates/networks/_create.html:23
+#: dashboards/project/networks/templates/networks/_update.html:23
+#: dashboards/project/networks/templates/networks/subnets/_create.html:24
+#: dashboards/project/networks/templates/networks/subnets/_update.html:32
+#: dashboards/project/volumes/templates/volumes/_attach.html:24
+#: dashboards/project/volumes/templates/volumes/_create.html:56
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:24
+#: dashboards/settings/ec2/templates/ec2/download_form.html:24
+#: dashboards/settings/project/templates/project/_openrc.html:31
+#: dashboards/settings/user/templates/user/_settings.html:24
+msgid "Cancel"
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:18
+#, fuzzy
+msgid "From here you can alter the sizing of the current flavor."
+msgstr "Tutaj można zarządzać użytkownikami i rolami."
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:19
+msgid ""
+"Note: this will not affect the resources allocated to any existing instances "
+"using this flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:24
+#: dashboards/admin/projects/workflows.py:270
+#: dashboards/settings/user/templates/user/_settings.html:23
+msgid "Save"
+msgstr ""
+
+#: dashboards/admin/images/panel.py:29 dashboards/admin/images/tables.py:44
+#: dashboards/admin/images/templates/images/index.html:3
+#: dashboards/admin/images/templates/images/index.html:6
+#: dashboards/project/images_and_snapshots/images/tables.py:47
+#: dashboards/project/images_and_snapshots/images/tables.py:132
+msgid "Images"
+msgstr "Obrazy"
+
+#: dashboards/admin/images/tables.py:40
+#: dashboards/project/images_and_snapshots/images/tables.py:113
+#: dashboards/project/instances/templates/instances/_detail_overview.html:74
+#, fuzzy
+msgid "Image Name"
+msgstr "Obrazy"
+
+#: dashboards/admin/images/views.py:55
+#, fuzzy
+msgid "Unable to retrieve image list."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/admin/images/templates/images/_update.html:8
+#: dashboards/admin/images/templates/images/_update.html:23
+#: dashboards/admin/images/templates/images/update.html:4
+#: dashboards/admin/images/templates/images/update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:22
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:6
+msgid "Update Image"
+msgstr "Aktualizuj obraz"
+
+#: dashboards/admin/images/templates/images/_update.html:18
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:17
+#, fuzzy
+msgid "From here you can modify different properties of an image."
+msgstr "Tutaj można zarządzać użytkownikami i rolami."
+
+#: dashboards/admin/instances/panel.py:29
+#: dashboards/admin/instances/tables.py:94
+#: dashboards/admin/instances/templates/instances/index.html:3
+#: dashboards/admin/projects/workflows.py:40
+#: dashboards/project/instances/panel.py:25
+#: dashboards/project/instances/tables.py:70
+#: dashboards/project/instances/tables.py:90
+#: dashboards/project/instances/tables.py:107
+#: dashboards/project/instances/tables.py:136
+#: dashboards/project/instances/tables.py:313
+#: dashboards/project/instances/templates/instances/index.html:3
+#: dashboards/project/instances/templates/instances/index.html:6
+msgid "Instances"
+msgstr "Instancje"
+
+#: dashboards/admin/instances/tables.py:60 usage/tables.py:30
+#, fuzzy
+msgid "Project Name"
+msgstr "Usuń projekt"
+
+#: dashboards/admin/instances/tables.py:67
+#: dashboards/admin/services/tables.py:40
+msgid "Host"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:71
+#: dashboards/project/instances/tables.py:290
+#: dashboards/project/instances/workflows.py:176 usage/tables.py:57
+#, fuzzy
+msgid "Instance Name"
+msgstr "Instancje"
+
+#: dashboards/admin/instances/tables.py:72
+#: dashboards/project/access_and_security/floating_ips/tables.py:111
+#: dashboards/project/access_and_security/floating_ips/workflows.py:32
+#: dashboards/project/access_and_security/floating_ips/workflows.py:39
+#: dashboards/project/instances/tables.py:291
+msgid "IP Address"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:74
+#: dashboards/project/containers/tables.py:256
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:30
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:37
+#: dashboards/project/instances/tables.py:293
+#: dashboards/project/volumes/tables.py:150
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:26
+msgid "Size"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:79
+#: dashboards/admin/networks/tables.py:74
+#: dashboards/admin/networks/ports/tables.py:77
+#: dashboards/project/images_and_snapshots/images/tables.py:119
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:13
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:18
+#: dashboards/project/instances/tables.py:298
+#: dashboards/project/instances/templates/instances/_detail_overview.html:13
+#: dashboards/project/networks/tables.py:100
+#: dashboards/project/networks/ports/tables.py:44
+#: dashboards/project/networks/templates/networks/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:30
+#: dashboards/project/volumes/tables.py:154
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:17
+msgid "Status"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:83
+#: dashboards/project/instances/tables.py:302
+msgid "Task"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:90
+#: dashboards/project/instances/tables.py:309
+msgid "Power State"
+msgstr ""
+
+#: dashboards/admin/instances/views.py:49
+#: dashboards/project/access_and_security/views.py:76
+#: dashboards/project/access_and_security/floating_ips/workflows.py:65
+#, fuzzy
+msgid "Unable to retrieve instance list."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/admin/instances/views.py:63
+#: dashboards/admin/networks/views.py:48
+#, fuzzy
+msgid "Unable to retrieve instance tenant information."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/admin/instances/views.py:80
+#: dashboards/project/instances/views.py:82
+#, fuzzy
+msgid "Unable to retrieve instance size information."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/admin/instances/templates/instances/index.html:6
+#, fuzzy
+msgid "All Instances"
+msgstr "Instancje"
+
+#: dashboards/admin/networks/forms.py:36
+#: dashboards/admin/networks/tables.py:67
+#: dashboards/admin/projects/tables.py:65 dashboards/project/dashboard.py:40
+#: dashboards/project/instances/workflows.py:38
+#, fuzzy
+msgid "Project"
+msgstr "Usuń projekt"
+
+#: dashboards/admin/networks/forms.py:37 dashboards/admin/networks/forms.py:74
+#: dashboards/admin/networks/tables.py:72
+#: dashboards/project/networks/tables.py:98
+#: dashboards/project/networks/templates/networks/_detail_overview.html:17
+msgid "Shared"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:46 dashboards/admin/users/forms.py:42
+#, fuzzy
+msgid "Select a project"
+msgstr "Usuń projekt"
+
+#: dashboards/admin/networks/forms.py:58
+#, fuzzy, python-format
+msgid "Network %s was successfully created."
+msgstr "Klucz %s został pomyślnie usunięty."
+
+#: dashboards/admin/networks/forms.py:64
+#, fuzzy, python-format
+msgid "Failed to create network %s"
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/admin/networks/forms.py:71
+#: dashboards/admin/networks/templates/networks/ports/_update.html:12
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:12
+#: dashboards/admin/users/forms.py:114
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:11
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:12
+#: dashboards/project/instances/templates/instances/_detail_overview.html:11
+#: dashboards/project/networks/forms.py:39
+#: dashboards/project/networks/templates/networks/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_update.html:12
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:11
+msgid "ID"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:82
+#: dashboards/project/networks/forms.py:48
+#, fuzzy, python-format
+msgid "Network %s was successfully updated."
+msgstr "Klucz %s został pomyślnie usunięty."
+
+#: dashboards/admin/networks/forms.py:87
+#: dashboards/project/networks/forms.py:53
+#, fuzzy, python-format
+msgid "Failed to update network %s"
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/admin/networks/panel.py:25
+#: dashboards/admin/networks/tables.py:35
+#: dashboards/admin/networks/tables.py:80
+#: dashboards/admin/networks/templates/networks/index.html:3
+#: dashboards/admin/networks/templates/networks/index.html:6
+#: dashboards/project/instances/workflows.py:412
+#: dashboards/project/networks/panel.py:25
+#: dashboards/project/networks/tables.py:44
+#: dashboards/project/networks/tables.py:106
+#: dashboards/project/networks/templates/networks/index.html:3
+#: dashboards/project/networks/templates/networks/index.html:6
+msgid "Networks"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:34
+#: dashboards/project/networks/tables.py:43
+#: dashboards/project/networks/templates/networks/subnets/index.html:3
+#: dashboards/project/networks/templates/networks/subnets/index.html:6
+msgid "Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:41
+#: dashboards/project/networks/tables.py:59
+#, python-format
+msgid "Failed to delete network %s"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:49
+#: dashboards/admin/networks/templates/networks/_create.html:8
+#: dashboards/admin/networks/templates/networks/_create.html:23
+#: dashboards/admin/networks/templates/networks/create.html:3
+#: dashboards/admin/networks/templates/networks/create.html:6
+#: dashboards/project/networks/tables.py:67
+#: dashboards/project/networks/workflows.py:111
+#: dashboards/project/networks/templates/networks/_create.html:7
+#: dashboards/project/networks/templates/networks/_create.html:22
+#: dashboards/project/networks/templates/networks/create.html:3
+#: dashboards/project/networks/templates/networks/create.html:6
+#, fuzzy
+msgid "Create Network"
+msgstr "Utwórz nowy wolumen."
+
+#: dashboards/admin/networks/tables.py:56
+#: dashboards/admin/networks/templates/networks/_update.html:7
+#: dashboards/project/networks/tables.py:74
+#: dashboards/project/networks/templates/networks/_update.html:7
+msgid "Edit Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:68
+#: dashboards/admin/networks/ports/forms.py:33
+#: dashboards/project/networks/subnets/forms.py:35
+#, fuzzy
+msgid "Network Name"
+msgstr "Obrazy"
+
+#: dashboards/admin/networks/tables.py:71
+#: dashboards/project/networks/tables.py:97
+#, fuzzy
+msgid "Subnets Associated"
+msgstr "Aktualizuj instncję"
+
+#: dashboards/admin/networks/tables.py:76
+#: dashboards/admin/networks/ports/tables.py:79
+#: dashboards/project/networks/tables.py:102
+#: dashboards/project/networks/ports/tables.py:46
+#: dashboards/project/networks/templates/networks/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:32
+#, fuzzy
+msgid "Admin State"
+msgstr "Położenie"
+
+#: dashboards/admin/networks/views.py:60
+#: dashboards/project/networks/views.py:52
+msgid "Network list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:91
+#: dashboards/project/networks/views.py:109
+msgid "Subnet list can not be retrieved."
msgstr ""
+#: dashboards/admin/networks/views.py:103
+#: dashboards/project/networks/views.py:121
+msgid "Port list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:118
+#: dashboards/project/networks/views.py:134
+#: dashboards/project/networks/subnets/tables.py:96
+#, fuzzy, python-format
+msgid "Unable to retrieve details for network \"%s\"."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/admin/networks/ports/forms.py:36
+#: dashboards/project/networks/subnets/forms.py:39
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:13
+msgid "Network ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:42
+#: dashboards/admin/networks/ports/forms.py:74
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:34
+msgid "Device ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:54
+#, fuzzy, python-format
+msgid "Port %s was successfully created."
+msgstr "Klucz %s został pomyślnie usunięty."
+
+#: dashboards/admin/networks/ports/forms.py:59
+#, fuzzy, python-format
+msgid "Failed to create a port for network %s"
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/admin/networks/ports/forms.py:84
+#, fuzzy, python-format
+msgid "Port %s was successfully updated."
+msgstr "Klucz %s został pomyślnie usunięty."
+
+#: dashboards/admin/networks/ports/forms.py:89
+#, fuzzy, python-format
+msgid "Failed to update port %s"
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/admin/networks/ports/tables.py:34
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:6
+msgid "Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:35
+#: dashboards/admin/networks/ports/tables.py:83
+#: dashboards/project/networks/ports/tables.py:53
+msgid "Ports"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:41
+#: dashboards/admin/networks/subnets/tables.py:39
+#: dashboards/project/networks/subnets/tables.py:51
+#, python-format
+msgid "Failed to delete subnet %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:51
+#: dashboards/admin/networks/templates/networks/ports/_create.html:8
+#: dashboards/admin/networks/templates/networks/ports/_create.html:23
+#: dashboards/admin/networks/templates/networks/ports/create.html:3
+#: dashboards/admin/networks/templates/networks/ports/create.html:6
+#, fuzzy
+msgid "Create Port"
+msgstr "Usuń projekt"
+
+#: dashboards/admin/networks/ports/tables.py:62
+#: dashboards/admin/networks/templates/networks/ports/_update.html:7
+#, fuzzy
+msgid "Edit Port"
+msgstr "Usuń projekt"
+
+#: dashboards/admin/networks/ports/tables.py:75
+#: dashboards/project/networks/ports/tables.py:42
+msgid "Fixed IPs"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:76
+#: dashboards/project/networks/ports/tables.py:43
+#, fuzzy
+msgid "Device Attached"
+msgstr "Dołącz wolumen"
+
+#: dashboards/admin/networks/ports/tabs.py:32
+#: dashboards/admin/overview/panel.py:29
+#: dashboards/admin/overview/templates/overview/usage.html:6
+#: dashboards/project/images_and_snapshots/images/tabs.py:27
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:27
+#: dashboards/project/instances/tabs.py:26
+#: dashboards/project/networks/ports/tabs.py:32
+#: dashboards/project/networks/subnets/tabs.py:32
+#: dashboards/project/overview/panel.py:29
+#: dashboards/project/overview/templates/overview/usage.html:6
+#: dashboards/project/volumes/tabs.py:27
+msgid "Overview"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tabs.py:42
+#: dashboards/project/networks/ports/tabs.py:42
+#, fuzzy
+msgid "Unable to retrieve port details."
+msgstr "Nie można utworzyć wolumenu: %s"
+
+#: dashboards/admin/networks/ports/views.py:49
+#: dashboards/admin/networks/subnets/views.py:49
+#: dashboards/project/networks/subnets/views.py:54
+#, fuzzy
+msgid "Unable to retrieve network."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/admin/networks/ports/views.py:82
+#, fuzzy
+msgid "Unable to retrieve port details"
+msgstr "Nie można utworzyć wolumenu: %s"
+
+#: dashboards/admin/networks/subnets/forms.py:43
+#, fuzzy, python-format
+msgid "Failed to retrieve network %s for a subnet"
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/admin/networks/subnets/tables.py:32
+#: dashboards/project/networks/subnets/tables.py:44
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:6
+msgid "Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:33
+#: dashboards/admin/networks/subnets/tables.py:81
+#: dashboards/project/networks/subnets/tables.py:45
+#: dashboards/project/networks/subnets/tables.py:104
+msgid "Subnets"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:49
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:8
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:23
+#: dashboards/admin/networks/templates/networks/subnets/create.html:3
+#: dashboards/admin/networks/templates/networks/subnets/create.html:6
+#: dashboards/project/networks/workflows.py:53
+#: dashboards/project/networks/subnets/tables.py:61
+#: dashboards/project/networks/templates/networks/subnets/_create.html:8
+#: dashboards/project/networks/templates/networks/subnets/_create.html:23
+#: dashboards/project/networks/templates/networks/subnets/create.html:3
+#: dashboards/project/networks/templates/networks/subnets/create.html:6
+#, fuzzy
+msgid "Create Subnet"
+msgstr "Wolumeny"
+
+#: dashboards/admin/networks/subnets/tables.py:60
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:7
+#: dashboards/project/networks/subnets/tables.py:72
+#: dashboards/project/networks/templates/networks/subnets/_update.html:7
+#, fuzzy
+msgid "Edit Subnet"
+msgstr "Edytuj role użytkowników"
+
+#: dashboards/admin/networks/subnets/tables.py:72
+#: dashboards/project/access_and_security/security_groups/forms.py:91
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:15
+msgid "CIDR"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:73
+#: dashboards/project/networks/workflows.py:66
+#: dashboards/project/networks/subnets/forms.py:53
+#: dashboards/project/networks/subnets/tables.py:85
+msgid "IP Version"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:74
+#: dashboards/project/networks/subnets/forms.py:54
+#: dashboards/project/networks/subnets/forms.py:104
+#: dashboards/project/networks/subnets/tables.py:86
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:19
+msgid "Gateway IP"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/views.py:82
+#: dashboards/project/networks/subnets/views.py:86
+#, fuzzy
+msgid "Unable to retrieve subnet details"
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/admin/networks/templates/networks/_create.html:18
+#: dashboards/project/networks/templates/networks/_create.html:17
+msgid "Select a name for your network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:16
+#: dashboards/admin/networks/templates/networks/ports/_update.html:21
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:25
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:17
+#: dashboards/project/instances/templates/instances/_update.html:16
+#: dashboards/project/networks/templates/networks/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_update.html:25
+#: dashboards/settings/ec2/templates/ec2/download_form.html:17
+#: dashboards/settings/project/templates/project/_openrc.html:24
+#: dashboards/settings/user/templates/user/_settings.html:17
+msgid "Description:"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:17
+#: dashboards/project/networks/templates/networks/_update.html:17
+msgid "You may update the editable properties of your network here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:22
+#: dashboards/admin/networks/templates/networks/ports/_update.html:27
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:31
+#: dashboards/project/instances/templates/instances/_update.html:22
+#: dashboards/project/networks/templates/networks/_update.html:22
+#: dashboards/project/networks/templates/networks/subnets/_update.html:31
+msgid "Save Changes"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/update.html:3
+#: dashboards/admin/networks/templates/networks/update.html:6
+#: dashboards/project/networks/templates/networks/update.html:3
+#: dashboards/project/networks/templates/networks/update.html:6
+#, fuzzy
+msgid "Update Network"
+msgstr "Aktualizuj obraz"
+
+#: dashboards/admin/networks/templates/networks/ports/_create.html:18
+msgid ""
+"You can create a port for the network. If you specify device ID to be "
+"attached, the device specified will be attached to the port created."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_update.html:22
+msgid "You may update the editable properties of your port here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/update.html:3
+#: dashboards/admin/networks/templates/networks/ports/update.html:6
+#, fuzzy
+msgid "Update Port"
+msgstr "Usuń projekt"
+
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:18
+#: dashboards/project/networks/templates/networks/subnets/_create.html:18
+msgid ""
+"You can create a subnet for the network. Any network address can be "
+"specified unless the network address does not overlap other subnets in the "
+"network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:14
+#: dashboards/project/networks/workflows.py:58
+#: dashboards/project/networks/subnets/forms.py:45
+#: dashboards/project/networks/subnets/tables.py:84
+#: dashboards/project/networks/templates/networks/subnets/_update.html:14
+msgid "Network Address"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:17
+#: dashboards/project/networks/templates/networks/subnets/_update.html:16
+msgid "IP version"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:26
+#: dashboards/project/networks/templates/networks/subnets/_update.html:26
+msgid "You may update the editable properties of your subnet here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/index.html:3
+#: dashboards/admin/networks/templates/networks/subnets/index.html:6
+#: dashboards/project/networks/templates/networks/detail.html:3
+#, fuzzy
+msgid "Network Detail"
+msgstr "Wolumeny"
+
+#: dashboards/admin/networks/templates/networks/subnets/update.html:3
+#: dashboards/admin/networks/templates/networks/subnets/update.html:6
+#: dashboards/project/networks/templates/networks/subnets/update.html:3
+#: dashboards/project/networks/templates/networks/subnets/update.html:6
+#, fuzzy
+msgid "Update Subnet"
+msgstr "Aktualizuj instncję"
+
+#: dashboards/admin/overview/templates/overview/usage.html:3
+msgid "Usage Overview"
+msgstr ""
+
+#: dashboards/admin/overview/templates/overview/usage.html:12
+msgid "Monitoring"
+msgstr ""
+
+#: dashboards/admin/projects/panel.py:29
+#: dashboards/admin/projects/tables.py:66
+#: dashboards/admin/projects/tables.py:95
+#: dashboards/admin/projects/templates/projects/index.html:8
#: templates/403.html:24 templates/404.html:23 templates/500.html:23
+#, fuzzy
msgid "Projects"
+msgstr "Usuń projekt"
+
+#: dashboards/admin/projects/tables.py:19
+msgid "Modify Users"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:32
+msgid "View Usage"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:39
+#: dashboards/admin/projects/templates/projects/_create.html:8
+#: dashboards/admin/projects/templates/projects/_create.html:23
+#: dashboards/admin/projects/templates/projects/create.html:6
+#, fuzzy
+msgid "Create Project"
+msgstr "Usuń projekt"
+
+#: dashboards/admin/projects/tables.py:46
+#: dashboards/admin/projects/workflows.py:269
+#: dashboards/admin/projects/templates/projects/update.html:3
+#: dashboards/admin/projects/templates/projects/update.html:6
+#, fuzzy
+msgid "Edit Project"
+msgstr "Usuń projekt"
+
+#: dashboards/admin/projects/tables.py:90
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:60
+#: dashboards/project/networks/templates/networks/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:15
+msgid "Project ID"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:91
+#: dashboards/admin/projects/workflows.py:76
+#: dashboards/admin/projects/workflows.py:251
+#: dashboards/admin/services/tables.py:42 dashboards/admin/users/tables.py:40
+#: dashboards/admin/users/tables.py:115
+msgid "Enabled"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:104
+#, fuzzy
+msgid "Remove"
+msgstr "Usuń obraz"
+
+#: dashboards/admin/projects/tables.py:105
+#, fuzzy
+msgid "Removed"
+msgstr "Usuń obraz"
+
+#: dashboards/admin/projects/tables.py:106 dashboards/admin/users/tables.py:41
+#: dashboards/admin/users/tables.py:75
+#: dashboards/project/instances/workflows.py:39
+msgid "User"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:107 dashboards/admin/users/panel.py:29
+#: dashboards/admin/users/tables.py:42 dashboards/admin/users/tables.py:76
+#: dashboards/admin/users/tables.py:122
+#: dashboards/admin/users/templates/users/index.html:8
+msgid "Users"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:125
+#, fuzzy
+msgid "Unable to retrieve role information."
+msgstr "Nie można wyrejestrować obrazu: %s"
+
+#: dashboards/admin/projects/tables.py:130
+msgid "Roles"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:134
+#, fuzzy
+msgid "Users For Project"
+msgstr "Usuń użytkownika z projektu"
+
+#: dashboards/admin/projects/tables.py:142
+msgid "Add To Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:154
+#, fuzzy
+msgid "Add New Users"
+msgstr "Utwórz nowy wolumen."
+
+#: dashboards/admin/projects/views.py:67
+#, fuzzy
+msgid "Unable to retrieve project information."
+msgstr "Nie można wyrejestrować obrazu: %s"
+
+#: dashboards/admin/projects/views.py:87
+#, fuzzy
+msgid "Unable to retrieve project list."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/admin/projects/views.py:110
+#, fuzzy
+msgid "Unable to retrieve users."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/admin/projects/views.py:154
+#, fuzzy
+msgid "Unable to retrieve default quota values."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/admin/projects/views.py:182
+#, fuzzy
+msgid "Unable to retrieve project details."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/admin/projects/workflows.py:37
+msgid "Injected File Content Bytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:38
+msgid "Metadata Items"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:41
+msgid "Injected Files"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:44
+#: dashboards/admin/volumes/panel.py:9 dashboards/admin/volumes/tables.py:15
+#: dashboards/admin/volumes/templates/volumes/index.html:3
+#: dashboards/admin/volumes/templates/volumes/index.html:6
+#: dashboards/project/volumes/panel.py:25
+#: dashboards/project/volumes/tables.py:38
+#: dashboards/project/volumes/tables.py:171
+#: dashboards/project/volumes/tables.py:183
+#: dashboards/project/volumes/templates/volumes/index.html:3
+#: dashboards/project/volumes/templates/volumes/index.html:6
+msgid "Volumes"
+msgstr "Wolumeny"
+
+#: dashboards/admin/projects/workflows.py:45
+msgid "Gigabytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:46
+msgid "RAM (MB)"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:47
+#: dashboards/project/access_and_security/floating_ips/tables.py:50
+#: dashboards/project/access_and_security/floating_ips/tables.py:128
+msgid "Floating IPs"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:50
+#, fuzzy
+msgid "Quota"
+msgstr "Aktualizuj instncję"
+
+#: dashboards/admin/projects/workflows.py:52
+#, fuzzy
+msgid "From here you can set quotas (max limits) for the project."
+msgstr "Tutaj można edytować wiele ról użytkowników."
+
+#: dashboards/admin/projects/workflows.py:81
+#: dashboards/admin/projects/workflows.py:254
+#, fuzzy
+msgid "Project Info"
+msgstr "Usuń projekt"
+
+#: dashboards/admin/projects/workflows.py:82
+#: dashboards/admin/projects/templates/projects/_create.html:18
+#, fuzzy
+msgid "From here you can create a new project to organize users."
+msgstr "Tutaj można edytować wiele ról użytkowników."
+
+#: dashboards/admin/projects/workflows.py:101
+#, fuzzy
+msgid "Unable to retrieve user list. Please try again later."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/admin/projects/workflows.py:155
+#: dashboards/admin/projects/templates/projects/_update_members.html:16
+#, fuzzy
+msgid "Project Members"
+msgstr "Usuń projekt"
+
+#: dashboards/admin/projects/workflows.py:169
+#: dashboards/admin/users/views.py:47
+#, fuzzy
+msgid "Unable to retrieve user list."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/admin/projects/workflows.py:180
+#, fuzzy
+msgid "Add Project"
+msgstr "Usuń projekt"
+
+#: dashboards/admin/projects/workflows.py:181
+msgid "Finish"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:182
+#, fuzzy, python-format
+msgid "Created new project \"%s\"."
+msgstr "Utwórz nowy wolumen."
+
+#: dashboards/admin/projects/workflows.py:183
+#, fuzzy, python-format
+msgid "Unable to create project \"%s\"."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/admin/projects/workflows.py:227
+#, fuzzy, python-format
+msgid "Failed to add %s project members and set project quotas."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/admin/projects/workflows.py:246
+#, fuzzy
+msgid "Unable to set project quotas."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/admin/projects/workflows.py:256
+#, fuzzy
+msgid "From here you can edit the project details."
+msgstr "Tutaj można edytować wiele ról użytkowników."
+
+#: dashboards/admin/projects/workflows.py:271
+#, python-format
+msgid "Modified project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:272
+#, fuzzy, python-format
+msgid "Unable to modify project \"%s\"."
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/admin/projects/workflows.py:342
+#, python-format
+msgid "Failed to modify %s project members and update project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:363
+msgid ""
+"Modified project information and members, but unable to modify project "
+"quotas."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:8
+#: dashboards/admin/projects/templates/projects/add_user.html:3
+#: dashboards/admin/projects/templates/projects/add_user.html:6
+#, fuzzy
+msgid "Add User To Project"
+msgstr "Usuń użytkownika z projektu"
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:18
+msgid "Select the user role for the project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:23
+msgid "Add"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:7
+#, python-format
+msgid "Create User for project '%(tenant_name)s'."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:18
+#, fuzzy
+msgid "From here you can create a new user to add to this project."
+msgstr "Tutaj można edytować wiele ról użytkowników."
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:23
+#: dashboards/admin/users/tables.py:20
+#: dashboards/admin/users/templates/users/_create.html:7
+#: dashboards/admin/users/templates/users/_create.html:22
+#: dashboards/admin/users/templates/users/create.html:7
+msgid "Create User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:7
+#: dashboards/admin/projects/templates/projects/_quotas.html:22
+#, fuzzy
+msgid "Update Quota"
+msgstr "Aktualizuj instncję"
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:17
+#, fuzzy, python-format
+msgid ""
+"From here you can edit quotas (max limits) for the project %(tenant.name)s."
+msgstr "Tutaj można edytować wiele ról użytkowników."
+
+#: dashboards/admin/projects/templates/projects/_update.html:8
+#: dashboards/admin/projects/templates/projects/_update.html:23
+#: dashboards/admin/projects/templates/projects/quotas.html:6
+#, fuzzy
+msgid "Update Project"
+msgstr "Usuń projekt"
+
+#: dashboards/admin/projects/templates/projects/_update.html:18
+#, fuzzy
+msgid "From here you can edit a project."
+msgstr "Tutaj można edytować wiele ról użytkowników."
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:7
+msgid ""
+"From here you can add and remove members to this project from the list of "
+"all available users."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:10
+#, fuzzy
+msgid "All Users"
+msgstr "Utwórz nowy wolumen."
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:25
+#: dashboards/admin/projects/templates/projects/_update_members.html:32
+msgid "No users found."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/create_user.html:3
+#: dashboards/admin/projects/templates/projects/create_user.html:6
+#, fuzzy
+msgid "Add New User"
+msgstr "Utwórz nowy wolumen."
+
+#: dashboards/admin/projects/templates/projects/usage.html:3
+msgid "Project Usage Overview"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:7
+msgid "Project Usage"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/users.html:7
+#, fuzzy
+msgid "Users for Project"
+msgstr "Usuń użytkownika z projektu"
+
+#: dashboards/admin/quotas/panel.py:29 dashboards/admin/quotas/tables.py:36
+#, fuzzy
+msgid "Quotas"
+msgstr "Aktualizuj instncję"
+
+#: dashboards/admin/quotas/tables.py:28
+msgid "Quota Name"
+msgstr ""
+
+#: dashboards/admin/quotas/tables.py:29
+msgid "Limit"
+msgstr ""
+
+#: dashboards/admin/quotas/views.py:46
+#, fuzzy
+msgid "Unable to get quota info."
+msgstr "Nie można ustawić widoczności obrazu na publiczną: %s"
+
+#: dashboards/admin/quotas/templates/quotas/index.html:8
+msgid "Default Quotas"
+msgstr ""
+
+#: dashboards/admin/services/panel.py:29
+#: dashboards/admin/services/tables.py:47
+#: dashboards/admin/services/templates/services/index.html:8
+msgid "Services"
+msgstr ""
+
+#: dashboards/admin/services/tables.py:37
+msgid "Id"
+msgstr ""
+
+#: dashboards/admin/services/tables.py:39
+msgid "Service"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:54
+msgid "Passwords do not match."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:62 dashboards/admin/users/forms.py:115
+#: dashboards/admin/users/tables.py:108
+msgid "User Name"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:63 dashboards/admin/users/forms.py:116
+#: dashboards/admin/users/tables.py:109
+msgid "Email"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:65 dashboards/admin/users/forms.py:117
+msgid "Password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:70 dashboards/admin/users/forms.py:124
+msgid "Confirm Password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:73 dashboards/admin/users/forms.py:127
+msgid "Primary Project"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:75
+msgid "Role"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:96
+#, fuzzy, python-format
+msgid "User \"%s\" was successfully created."
+msgstr "Klucz %s został pomyślnie usunięty."
+
+#: dashboards/admin/users/forms.py:106
+#, fuzzy
+msgid "Unable to add userto primary project."
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/admin/users/forms.py:110
+#, fuzzy
+msgid "Unable to create user."
+msgstr "Nie można utworzyć wolumenu: %s"
+
+#: dashboards/admin/users/forms.py:151
+msgid "name"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:151
+msgid "email"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:160
+msgid "primary project"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:173
+#, python-format
+msgid "The user %s has no role defined for"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:181
+msgid "password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:190
+#, fuzzy
+msgid "User has been updated successfully."
+msgstr "Wolumen %(id)s %(name)s został pomyślnie utworzony."
+
+#: dashboards/admin/users/forms.py:194
+#, fuzzy, python-format
+msgid "Unable to update %(attributes)s for the user."
+msgstr "Nie można usunąć klucza: %s"
+
+#: dashboards/admin/users/tables.py:32
+#: dashboards/project/images_and_snapshots/images/tables.py:68
+msgid "Edit"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:39
+msgid "Enable"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:39
+msgid "Disable"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:40
+msgid "Disabled"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:63
+msgid "You cannot disable the user you are currently logged in as."
+msgstr ""
+
+#: dashboards/admin/users/tables.py:114
+msgid "User ID"
+msgstr ""
+
+#: dashboards/admin/users/views.py:70
+#, fuzzy
+msgid "Unable to update user."
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/admin/users/views.py:104
+#, fuzzy
+msgid "Unable to retrieve user roles."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/admin/users/templates/users/_create.html:17
+#, fuzzy
+msgid "From here you can create a new user and assign them to a project."
+msgstr "Tutaj można edytować wiele ról użytkowników."
+
+#: dashboards/admin/users/templates/users/_update.html:7
+#: dashboards/admin/users/templates/users/_update.html:22
+#: dashboards/admin/users/templates/users/update.html:7
+#, fuzzy
+msgid "Update User"
+msgstr "Aktualizuj obraz"
+
+#: dashboards/admin/users/templates/users/_update.html:17
+#, fuzzy
+msgid ""
+"From here you can edit the user's details, including their default project."
+msgstr "Tutaj można edytować wiele ról użytkowników."
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:3
+#: dashboards/project/volumes/templates/volumes/detail.html:3
+#, fuzzy
+msgid "Volume Details"
+msgstr "Wolumeny"
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:6
+#: dashboards/project/volumes/templates/volumes/detail.html:6
+#, fuzzy
+msgid "Volume Detail"
+msgstr "Wolumeny"
+
+#: dashboards/project/dashboard.py:24
+msgid "Manage Compute"
+msgstr ""
+
+#: dashboards/project/dashboard.py:35
+msgid "Object Store"
+msgstr ""
+
+#: dashboards/project/access_and_security/panel.py:26
+#: dashboards/project/instances/workflows.py:348
+msgid "Access & Security"
+msgstr ""
+
+#: dashboards/project/access_and_security/views.py:51
+#, fuzzy
+msgid "Unable to retrieve keypair list."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/access_and_security/views.py:60
+#: dashboards/project/access_and_security/security_groups/views.py:74
+#, fuzzy
+msgid "Unable to retrieve security groups."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/access_and_security/views.py:69
+#: dashboards/project/access_and_security/floating_ips/workflows.py:49
+#, fuzzy
+msgid "Unable to retrieve floating IP addresses."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:32
+msgid "Pool"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:43
+#, fuzzy, python-format
+msgid "Allocated Floating IP %(ip)s."
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:47
+#, fuzzy
+msgid "Unable to allocate Floating IP."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:37
+#, fuzzy
+msgid "Allocate IP To Project"
+msgstr "Usuń projekt"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:47
+msgid "Release"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:48
+msgid "Released"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:49
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:22
+msgid "Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:6
+#: dashboards/project/instances/tables.py:219
+msgid "Associate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:76
+msgid "Disassociate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:90
+#, python-format
+msgid "Successfully disassociated Floating IP: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:94
+#, fuzzy
+msgid "Unable to disassociate floating IP."
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:114
+#: dashboards/project/access_and_security/floating_ips/workflows.py:36
+#: dashboards/project/instances/tables.py:69
+#: dashboards/project/instances/tables.py:89
+#: dashboards/project/instances/tables.py:106
+#: dashboards/project/instances/tables.py:135
+#: dashboards/project/volumes/tables.py:206
+#, fuzzy
+msgid "Instance"
+msgstr "Instancje"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:117
+msgid "Floating IP Pool"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:65
+#, fuzzy
+msgid "Unable to retrieve floating IP pools."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/access_and_security/floating_ips/views.py:68
+msgid "No floating IP pools available."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:40
+msgid "Select the IP address you wish to associate with the selected instance."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:53
+#, fuzzy
+msgid "Select an IP address"
+msgstr "Usuń projekt"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:55
+#, fuzzy
+msgid "No IP addresses available"
+msgstr "brak dostępnych"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:76
+#: dashboards/project/volumes/forms.py:160
+#, fuzzy
+msgid "Select an instance"
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:78
+#: dashboards/project/volumes/forms.py:162
+#, fuzzy
+msgid "No instances available"
+msgstr "brak dostępnych"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:97
+msgid "Manage Floating IP Associations"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:98
+#, fuzzy
+msgid "Associate"
+msgstr "Aktualizuj instncję"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:99
+#, python-format
+msgid "IP address %s associated."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:100
+#, fuzzy, python-format
+msgid "Unable to associate IP address %s."
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:38
+#: dashboards/project/access_and_security/keypairs/forms.py:49
+#: dashboards/project/access_and_security/keypairs/tables.py:52
+msgid "Keypair Name"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:40
+msgid ""
+"Keypair names may only contain letters, numbers, underscores and hyphens."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:51
+#, fuzzy
+msgid "Public Key"
+msgstr "Uczyń publicznym"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:60
+#, python-format
+msgid "Successfully imported public key: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:65
+#, fuzzy
+msgid "Unable to import keypair."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:30
+#: dashboards/project/instances/tables.py:295
+#: dashboards/project/instances/workflows.py:335
+msgid "Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:31
+#: dashboards/project/access_and_security/keypairs/tables.py:60
+msgid "Keypairs"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:39
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html:6
+msgid "Import Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:46
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html:6
+msgid "Create Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:53
+msgid "Fingerprint"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/views.py:74
+#, fuzzy, python-format
+msgid "Unable to create keypair: %(exc)s"
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:46
+#, fuzzy, python-format
+msgid "Successfully created security group: %s"
+msgstr "Nie można utworzyć grupy bezpieczeństwa: %s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:52
+#, fuzzy
+msgid "Unable to create security group."
+msgstr "Grupy bezpieczeństwa"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:57
+#: dashboards/project/access_and_security/security_groups/tables.py:93
+msgid "IP Protocol"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:61
+msgid "The protocol which this rule should be applied to."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:65
+#: dashboards/project/access_and_security/security_groups/forms.py:71
+#: dashboards/project/access_and_security/security_groups/tables.py:95
+msgid "From Port"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:66
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP type in the range (-1: 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:72
+#: dashboards/project/images_and_snapshots/images/tables.py:115
+msgid "Type"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:74
+#: dashboards/project/access_and_security/security_groups/forms.py:80
+#: dashboards/project/access_and_security/security_groups/tables.py:96
+msgid "To Port"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:75
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP code in the range (-1: 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:81
+msgid "Code"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:84
+#, fuzzy
+msgid "Source Group"
+msgstr "Grupy bezpieczeństwa"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:86
+msgid ""
+"To specify an allowed IP range, select CIDR. To allow access from all "
+"members of another security group select Source Group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:94
+msgid "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:121
+msgid "The ICMP type is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:124
+msgid "The ICMP code is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:127
+msgid "The ICMP type not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:130
+msgid "The ICMP code not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:134
+msgid "The \"from\" port number is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:137
+msgid "The \"to\" port number is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:140
+msgid ""
+"The \"to\" port number must be greater than or equal to the \"from\" port "
+"number."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:146
+msgid "Either CIDR or Source Group may be specified, but not both."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:168
+#, fuzzy, python-format
+msgid "Successfully added rule: %s"
+msgstr "Pomyślnie zmodyfikowano projekt %(proj)s."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:173
+#, fuzzy
+msgid "Unable to add rule to security group."
+msgstr "Grupy bezpieczeństwa"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:31
+#, fuzzy
+msgid "Security Group"
+msgstr "Grupy bezpieczeństwa"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:32
+#: dashboards/project/access_and_security/security_groups/tables.py:66
+#: dashboards/project/instances/workflows.py:340
+#: dashboards/project/instances/templates/instances/_detail_overview.html:49
+msgid "Security Groups"
+msgstr "Grupy bezpieczeństwa"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:45
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html:6
+#, fuzzy
+msgid "Create Security Group"
+msgstr "Grupy bezpieczeństwa"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:52
+#, fuzzy
+msgid "Edit Rules"
+msgstr "Edytuj role użytkowników"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:72
+msgid "Rule"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:73
+#, fuzzy
+msgid "Rules"
+msgstr "Edytuj role użytkowników"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:97
+msgid "Source"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:107
+#, fuzzy
+msgid "Security Group Rules"
+msgstr "Grupy bezpieczeństwa"
+
+#: dashboards/project/access_and_security/security_groups/views.py:60
+#, fuzzy
+msgid "Unable to retrieve security group."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/access_and_security/security_groups/views.py:80
+#, python-format
+msgid "%s (current)"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/index.html:6
+msgid "Access &amp; Security"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:8
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html:3
+#, fuzzy
+msgid "Allocate Floating IP"
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:18
+msgid "Allocate a floating IP from a given floating ip pool."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:20
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:19
+msgid "Project Quotas"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:31
+msgid "Allocate IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:17
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:17
+#, fuzzy
+msgid ""
+"Keypairs are ssh credentials which are injected into images when they are "
+"launched. Creating a new key pair registers the public key and downloads the "
+"private key (a .pem file)."
+msgstr ""
+"Pary kluczy to dane uwierzytelniające ssh, które są wstrzykiwane do "
+"instancji podczas uruchomienia. Utworzenie nowej pary rejestruje klucz "
+"publiczny umożliwia pobranie klucza prywatnego (pliku pem). <em>Należy "
+"chronić i używać ten klucza tak jak normalnego klucza prywantego.</em>"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:18
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:18
+msgid "Protect and use the key as you would any normal ssh private key."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:6
+msgid "Download Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:11
+#, python-format
+msgid ""
+"The keypair &quot;%(keypair_name)s&quot; should download automatically. If "
+"not use the link below."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:15
+#, python-format
+msgid "Download keypair &quot;%(keypair_name)s&quot;"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:18
+#, fuzzy
+msgid "From here you can create a new security group"
+msgstr "Tutaj można edytować wiele ról użytkowników."
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:9
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html:6
+#, fuzzy
+msgid "Edit Security Group Rules"
+msgstr "Grupy bezpieczeństwa"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:12
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:19
+msgid "Add Rule"
+msgstr ""
+
+#: dashboards/project/containers/browsers.py:26
+msgid "Swift"
+msgstr ""
+
+#: dashboards/project/containers/browsers.py:29
+#: dashboards/project/containers/tables.py:40
+#, fuzzy
+msgid "Container"
+msgstr "Utwórz nowy wolumen."
+
+#: dashboards/project/containers/forms.py:39
+msgid "Slash is not an allowed character."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:49
+#: dashboards/project/containers/tables.py:121
+msgid "Container Name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:57
+#, fuzzy
+msgid "Container created successfully."
+msgstr "Wolumen %(id)s %(name)s został pomyślnie utworzony."
+
+#: dashboards/project/containers/forms.py:68
+#, fuzzy
+msgid "Folder created successfully."
+msgstr "Wolumen %(id)s %(name)s został pomyślnie utworzony."
+
+#: dashboards/project/containers/forms.py:71
+#, fuzzy
+msgid "Unable to create container."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/containers/forms.py:79
+#: dashboards/project/containers/tables.py:253
+msgid "Object Name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:81
+msgid "File"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:95
+#, fuzzy
+msgid "Object was successfully uploaded."
+msgstr "Grupa bezpieczeństwa %s została pomyślnie usunięta."
+
+#: dashboards/project/containers/forms.py:98
+#, fuzzy
+msgid "Unable to upload object."
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/project/containers/forms.py:102
+msgid "Destination container"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:106
+msgid "Destination object name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:137
+#: dashboards/project/containers/forms.py:163
+msgid "Unable to copy object."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:153
+#, python-format
+msgid "Copied \"%(orig)s\" to \"%(dest)s\" as \"%(new)s\"."
+msgstr ""
+
+#: dashboards/project/containers/panel.py:29
+#: dashboards/project/containers/tables.py:41
+#: dashboards/project/containers/tables.py:128
+#: dashboards/project/containers/templates/containers/index.html:7
+msgid "Containers"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:62
+#: dashboards/project/containers/templates/containers/_create.html:7
+#: dashboards/project/containers/templates/containers/_create.html:22
+#: dashboards/project/containers/templates/containers/create.html:6
+msgid "Create Container"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:69
+#, fuzzy
+msgid "View Container"
+msgstr "Utwórz nowy wolumen."
+
+#: dashboards/project/containers/tables.py:81
+#: dashboards/project/containers/templates/containers/_upload.html:23
+#: dashboards/project/containers/templates/containers/upload.html:3
+msgid "Upload Object"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:137
+#: dashboards/project/containers/tables.py:156
+#, fuzzy
+msgid "Object"
+msgstr "Usuń projekt"
+
+#: dashboards/project/containers/tables.py:138
+#: dashboards/project/containers/tables.py:157
+#: dashboards/project/containers/tables.py:263
+msgid "Objects"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:149
+msgid "Folder"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:150
+msgid "Folders"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:163
+msgid "Copy"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:176
+msgid "Download"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:232
+#, fuzzy
+msgid "Create Folder"
+msgstr "Wolumeny"
+
+#: dashboards/project/containers/views.py:53
+#, fuzzy
+msgid "Unable to retrieve container list."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/containers/views.py:82
+#, fuzzy
+msgid "Unable to retrieve object list."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/containers/views.py:166
+#, fuzzy
+msgid "Unable to retrieve object."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/containers/views.py:200
+#, fuzzy
+msgid "Unable to list containers."
+msgstr "Nie można usunąć klucza: %s"
+
+#: dashboards/project/containers/templates/containers/_copy.html:7
+#: dashboards/project/containers/templates/containers/_copy.html:22
+#: dashboards/project/containers/templates/containers/copy.html:3
+#: dashboards/project/containers/templates/containers/copy.html:6
+msgid "Copy Object"
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_copy.html:17
+msgid ""
+"Make a new copy of an existing object to store in this or another container. "
+"You may also specify a path at which the new copy should live inside of the "
+"selected container."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_create.html:17
+msgid ""
+"A container is a storage compartment for your data and provides a way for "
+"you to organize your data. You can think of a container as a folder in "
+"Windows &reg; or a directory in UNIX &reg;. The primary difference between a "
+"container and these other file system concepts is that containers cannot be "
+"nested. You can, however, create an unlimited number of containers within "
+"your account. Data must be stored in a container so you must have at least "
+"one container defined in your account prior to uploading data."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:8
+msgid "Upload Object To Container"
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:18
+msgid ""
+"An object is the basic storage entity and any optional metadata that "
+"represents the files you store in the OpenStack Object Storage system. When "
+"you upload data to OpenStack Object Storage, the data is stored as-is (no "
+"compression or encryption) and consists of a location (container), the "
+"object's name, and any metadata consisting of key/value pairs."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/upload.html:6
+msgid "Upload Objects"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/panel.py:26
+#, fuzzy
+msgid "Images & Snapshots"
+msgstr "Instancje"
+
+#: dashboards/project/images_and_snapshots/views.py:63
+#, fuzzy
+msgid "Unable to retrieve images."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/images_and_snapshots/views.py:74
+#, fuzzy
+msgid "Unable to retrieve snapshots."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/images_and_snapshots/views.py:82
+#: dashboards/project/volumes/forms.py:65
+#, fuzzy
+msgid "Unable to retrieve volume snapshots."
+msgstr "Nie można utworzyć wolumenu: %s"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:42
+#, fuzzy
+msgid "Image Location"
+msgstr "Położenie"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:43
+msgid "An external (HTTP) URL to load the image from."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:46
+#: dashboards/project/images_and_snapshots/images/forms.py:130
+#: dashboards/project/images_and_snapshots/images/tables.py:126
+msgid "Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:50
+msgid "AKI - Amazon Kernel Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:53
+msgid "AMI - Amazon Machine Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:56
+msgid "ARI - Amazon Ramdisk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:59
+msgid "ISO - Optical Disk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:61
+msgid "QCOW2 - QEMU Emulator"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:68
+msgid "Minimum Disk (GB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:69
+#: dashboards/project/images_and_snapshots/images/forms.py:76
+msgid ""
+"The minimum disk size required to boot the image. If unspecified, this value "
+"defaults to 0 (no minimum)."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:75
+msgid "Minimum Ram (MB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:82
+#: dashboards/project/images_and_snapshots/images/forms.py:134
+#: dashboards/project/images_and_snapshots/images/tables.py:123
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:15
+#, fuzzy
+msgid "Public"
+msgstr "Uczyń publicznym"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:106
+#, python-format
+msgid "Your image %s has been queued for creation."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:110
+#, fuzzy
+msgid "Unable to create new image."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:116
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:48
+msgid "Kernel ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:121
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:52
+msgid "Ramdisk ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:126
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:44
+msgid "Architecture"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:138
+#, fuzzy, python-format
+msgid "Unable to update image \"%s\"."
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:162
+#, fuzzy
+msgid "Image was successfully updated."
+msgstr "Obraz %s został pomyślnie wyrejestrowany."
+
+#: dashboards/project/images_and_snapshots/images/tables.py:34
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:33
+#: dashboards/project/instances/workflows.py:455
+#, fuzzy
+msgid "Launch"
+msgstr "Uruchom obraz"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:46
+#: dashboards/project/images_and_snapshots/images/tables.py:82
+#: dashboards/project/instances/workflows.py:168
+#: dashboards/project/instances/workflows.py:173
+#, fuzzy
+msgid "Image"
+msgstr "Obrazy"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:61
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:31
+#, fuzzy
+msgid "Create Image"
+msgstr "Aktualizuj obraz"
+
+#: dashboards/project/images_and_snapshots/images/tabs.py:38
+#, fuzzy
+msgid "Unable to retrieve image details."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/images_and_snapshots/images/views.py:61
+#, fuzzy
+msgid "Unable to retrieve image."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:37
+#, fuzzy
+msgid "Instance ID"
+msgstr "ID instancji:"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:40
+#: dashboards/project/volumes/forms.py:193
+msgid "Snapshot Name"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:50
+#, python-format
+msgid "Snapshot \"%(name)s\" created for instance \"%(inst)s\""
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:56
+#, fuzzy
+msgid "Unable to create snapshot."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:48
+#: dashboards/project/instances/workflows.py:107
+#: dashboards/project/instances/workflows.py:169
+msgid "Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:49
+msgid "Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:55
+#, fuzzy
+msgid "Instance Snapshots"
+msgstr "Instancje"
+
+#: dashboards/project/images_and_snapshots/snapshots/views.py:53
+#, fuzzy
+msgid "Unable to retrieve instance."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:6
+msgid "Images &amp; Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:6
+#, fuzzy
+msgid "Create An Image"
+msgstr "Aktualizuj obraz"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:18
+msgid "Specify an image to upload to the Image Service."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:21
+msgid ""
+"Currently only images available via an HTTP URL are supported. The image "
+"location must be accessible to the Image Service. Compressed image binaries "
+"are supported (.zip and .tar.gz.)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:24
+msgid "Please note: "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:25
+msgid ""
+"The Image Location field MUST be a valid and direct URL to the image binary. "
+"URLs that redirect or serve error pages will result in unusable images."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:3
+#, fuzzy
+msgid "Image Overview"
+msgstr "Instancje"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:6
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:7
+#: dashboards/project/instances/templates/instances/_detail_overview.html:6
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:6
+msgid "Info"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:17
+msgid "Checksum"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:19
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:39
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:28
+#, fuzzy
+msgid "Created"
+msgstr "Utwórz nowy wolumen."
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:21
+#, fuzzy
+msgid "Updated"
+msgstr "Aktualizuj obraz"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:27
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:34
+#: dashboards/project/instances/templates/instances/_detail_overview.html:19
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:23
+msgid "Specs"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:32
+msgid "Container Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:34
+msgid "Disk Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:40
+msgid "Custom Properties"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:56
+msgid "Euca2ools state"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:64
+#, fuzzy
+msgid "Image Type"
+msgstr "Obrazy"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html:4
+msgid "Image Detail "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:8
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:3
+#: dashboards/project/instances/tables.py:179
+#: dashboards/project/volumes/tables.py:76
+msgid "Create Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:18
+msgid "Snapshots preserve the disk state of a running instance."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:20
+#: dashboards/project/instances/workflows.py:75
+#: dashboards/project/instances/workflows.py:110
+#: dashboards/project/instances/templates/instances/_detail_overview.html:93
+#: dashboards/project/volumes/tables.py:37
+#: dashboards/project/volumes/tables.py:182
+#, fuzzy
+msgid "Volume"
+msgstr "Wolumeny"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:38
+#: dashboards/project/instances/templates/instances/_detail_overview.html:29
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:27
+msgid "GB"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:6
+msgid "Create a Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:3
+#, fuzzy
+msgid "Volume Snapshot Details"
+msgstr "Wolumeny"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:6
+#, fuzzy
+msgid "Volume Snapshot Detail"
+msgstr "Wolumeny"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:34
+#: dashboards/project/instances/workflows.py:76
+#, fuzzy
+msgid "Volume Snapshot"
+msgstr "Wolumeny"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:35
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:85
+#, fuzzy
+msgid "Volume Snapshots"
+msgstr "Wolumeny"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:43
+#: dashboards/project/volumes/tables.py:59
+#: dashboards/project/volumes/templates/volumes/_create.html:8
+#: dashboards/project/volumes/templates/volumes/_create.html:55
+#, fuzzy
+msgid "Create Volume"
+msgstr "Wolumeny"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:80
+#: dashboards/project/volumes/forms.py:26
+#, fuzzy
+msgid "Volume Name"
+msgstr "Wolumeny"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:41
+#, fuzzy
+msgid "Unable to retrieve snapshot details."
+msgstr "Nie można utworzyć wolumenu: %s"
+
+#: dashboards/project/instances/forms.py:45
+#, fuzzy, python-format
+msgid "Instance \"%s\" updated."
+msgstr "Instancja %s uruchomiona."
+
+#: dashboards/project/instances/forms.py:50
+#, fuzzy
+msgid "Unable to update instance."
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/project/instances/tables.py:67
+msgid "Terminate"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:68
+msgid "Scheduled termination of"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:87
+msgid "Reboot"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:88
+msgid "Rebooted"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:104
+msgid "Pause"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:104
+msgid "Unpause"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:105
+msgid "Paused"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:105
+msgid "Unpaused"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:133
+msgid "Suspend"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:133
+msgid "Resume"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:134
+msgid "Suspended"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:134
+msgid "Resumed"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:162
+#: dashboards/project/instances/workflows.py:454
+#: dashboards/project/instances/templates/instances/launch.html:3
+#: dashboards/project/instances/templates/instances/launch.html:6
+#, fuzzy
+msgid "Launch Instance"
+msgstr "Uruchom obraz"
+
+#: dashboards/project/instances/tables.py:169
+#: dashboards/project/instances/templates/instances/_update.html:7
+msgid "Edit Instance"
+msgstr "Edytuj instancję"
+
+#: dashboards/project/instances/tables.py:189
+msgid "VNC Console"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:204
+msgid "View Log"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:252
+#, python-format
+msgid "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disk"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:259
+#: dashboards/project/instances/tables.py:266
+#, fuzzy
+msgid "Not available"
+msgstr "brak dostępnych"
+
+#: dashboards/project/instances/tabs.py:36
+msgid "Log"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:48
+#: dashboards/project/instances/views.py:106
+#, fuzzy, python-format
+msgid "Unable to get log for instance \"%s\"."
+msgstr "Nie można zaktualizować instancji %(inst)s: %(msg)s"
+
+#: dashboards/project/instances/tabs.py:55
+msgid "VNC"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:70
+#: dashboards/project/instances/views.py:122
+#, fuzzy, python-format
+msgid "Unable to get VNC console for instance \"%s\"."
+msgstr "Nie można zaktualizować instancji %(inst)s: %(msg)s"
+
+#: dashboards/project/instances/views.py:59
+#, fuzzy
+msgid "Unable to retrieve instances."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/instances/views.py:144
+#, fuzzy
+msgid "Unable to retrieve instance details."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/instances/views.py:179
+#, fuzzy, python-format
+msgid "Unable to retrieve details for instance \"%s\"."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/instances/workflows.py:53
+#, fuzzy
+msgid "Project & User"
+msgstr "Usuń projekt"
+
+#: dashboards/project/instances/workflows.py:66
+msgid "Don't boot from a volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:67
+msgid "Boot from volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:68
+msgid "Boot from volume snapshot (creates a new volume)."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:72
+#: dashboards/project/instances/workflows.py:90
+#, fuzzy
+msgid "Volume Options"
+msgstr "Wolumeny"
+
+#: dashboards/project/instances/workflows.py:78
+#: dashboards/project/volumes/forms.py:126
+msgid "Device Name"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:81
+msgid "Volume mount point (e.g. 'vda' mounts at '/dev/vda')."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:83
+#, fuzzy
+msgid "Delete on Terminate"
+msgstr "Usuń projekt"
+
+#: dashboards/project/instances/workflows.py:86
+msgid "Delete volume on instance terminate"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:100
+#, python-format
+msgid "Please choose a volume, or select %s."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:117
+#, fuzzy
+msgid "Select Volume"
+msgstr "Wolumeny"
+
+#: dashboards/project/instances/workflows.py:125
+#, fuzzy
+msgid "Unable to retrieve list of volumes."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/instances/workflows.py:129
+#, fuzzy
+msgid "Select Volume Snapshot"
+msgstr "Utwórz nowy wolumen."
+
+#: dashboards/project/instances/workflows.py:138
+#, fuzzy
+msgid "Unable to retrieve list of volume snapshots."
+msgstr "Nie można utworzyć wolumenu: %s"
+
+#: dashboards/project/instances/workflows.py:171
+#, fuzzy
+msgid "Instance Source"
+msgstr "Instancje"
+
+#: dashboards/project/instances/workflows.py:174
+#, fuzzy
+msgid "Instance Snapshot"
+msgstr "Instancje"
+
+#: dashboards/project/instances/workflows.py:178
+msgid "Size of image to launch."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:179
+#, fuzzy
+msgid "Instance Count"
+msgstr "Instancje"
+
+#: dashboards/project/instances/workflows.py:182
+msgid "Number of instances to launch."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:185
+#, fuzzy
+msgid "Details"
+msgstr "Wolumeny"
+
+#: dashboards/project/instances/workflows.py:198
+msgid ""
+"There are no image sources available; you must first create an image before "
+"attempting to launch an instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:203
+msgid "Please select an option for the instance source."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:212
+msgid ""
+"Launching multiple instances is only supported for images and instance "
+"snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:229
+#, fuzzy
+msgid "Unable to retrieve public images."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/instances/workflows.py:244
+#, fuzzy
+msgid "Unable to retrieve images for the current project."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/instances/workflows.py:267
+#, fuzzy
+msgid "Select Image"
+msgstr "Wolumeny"
+
+#: dashboards/project/instances/workflows.py:269
+#, fuzzy
+msgid "No images available."
+msgstr "brak dostępnych"
+
+#: dashboards/project/instances/workflows.py:278
+#, fuzzy
+msgid "Select Instance Snapshot"
+msgstr "Instancje"
+
+#: dashboards/project/instances/workflows.py:280
+#, fuzzy
+msgid "No snapshots available."
+msgstr "brak dostępnych"
+
+#: dashboards/project/instances/workflows.py:291
+#, fuzzy
+msgid "Unable to retrieve instance flavors."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/instances/workflows.py:304 usage/base.py:114
+#, fuzzy
+msgid "Unable to retrieve quota information."
+msgstr "Nie można wyrejestrować obrazu: %s"
+
+#: dashboards/project/instances/workflows.py:337
+msgid "Which keypair to use for authentication."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:344
+#, fuzzy
+msgid "Launch instance in these security groups."
+msgstr "Nie można utworzyć grupy bezpieczeństwa: %s"
+
+#: dashboards/project/instances/workflows.py:349
+msgid ""
+"Control access to your instance via keypairs, security groups, and other "
+"mechanisms."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:359
+#, fuzzy
+msgid "Unable to retrieve keypairs."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/instances/workflows.py:361
+#, fuzzy
+msgid "Select a keypair"
+msgstr "Usuń projekt"
+
+#: dashboards/project/instances/workflows.py:363
+#, fuzzy
+msgid "No keypairs available."
+msgstr "brak dostępnych"
+
+#: dashboards/project/instances/workflows.py:372
+#, fuzzy
+msgid "Unable to retrieve list of security groups"
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/instances/workflows.py:392
+msgid "Customization Script"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:394
+msgid ""
+"A script or set of commands to be executed after the instance has been built "
+"(max 16kb)."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:401
+msgid "Post-Creation"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:415
+#, fuzzy
+msgid "Launch instance withthese networks"
+msgstr "Nie można utworzyć grupy bezpieczeństwa: %s"
+
+#: dashboards/project/instances/workflows.py:419
+msgid "Networking"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:421
+#, fuzzy
+msgid "Select networks for your instance."
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/project/instances/workflows.py:433
+#, fuzzy
+msgid "Unable to retrieve networks."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/instances/workflows.py:456
+#, python-format
+msgid "Launched %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:457
+#, fuzzy, python-format
+msgid "Unable to launch %(count)s named \"%(name)s\"."
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/project/instances/workflows.py:470
+#, fuzzy, python-format
+msgid "%s instances"
+msgstr "Instancje"
+
+#: dashboards/project/instances/workflows.py:473
+#, fuzzy
+msgid "instance"
+msgstr "Instancje"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:4
+#, fuzzy
+msgid "Instance Console Log"
+msgstr "Instancje"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:7
+msgid "Log Length"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:9
+msgid "Go"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:11
+msgid "View Full Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:3
+#, fuzzy
+msgid "Instance Overview"
+msgstr "Instancje"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:27
+msgid "VCPU"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:28
+#: usage/tables.py:20
+msgid "Disk"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:34
+msgid "IP Addresses"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:59
+msgid "No rules defined."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:68
+msgid "Meta"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:71
+#, fuzzy
+msgid "Key Name"
+msgstr "Obrazy"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:84
+#, fuzzy
+msgid "Volumes Attached"
+msgstr "Dołącz wolumen"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:88
+#: dashboards/project/volumes/tables.py:167
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:38
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:45
+#, fuzzy
+msgid "Attached To"
+msgstr "Dołącz wolumen"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:90
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:42
+msgid "on"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:94
+msgid "No volumes attached."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:3
+#, fuzzy
+msgid "Instance VNC Console"
+msgstr "Instancje"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid ""
+"If VNC console is not responding to keyboard input: click the grey status "
+"bar below."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid "Click here to show only VNC"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:8
+msgid "VNC console is currently unavailabe. Please try again later."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:9
+msgid "Reload"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:2
+msgid ""
+"You can customize your instance after it's launched using the options "
+"available here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:3
+msgid ""
+"The \"Customization Script\" field is analogous to \"User Data\" in other "
+"systems."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:3
+msgid "Specify the details for launching an instance."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:4
+msgid ""
+"The chart below shows the resources used by this project in relation to the "
+"project's quotas."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:6
+#, fuzzy
+msgid "Flavor Details"
+msgstr "Wolumeny"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+msgid "Total Disk"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "MB"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:21
+#, fuzzy
+msgid "Number of Instances"
+msgstr "Instancje"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:29
+msgid "Number of VCPUs"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "Total RAM"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_volumes_help.html:3
+msgid ""
+"An instance can be launched with varying types of attached storage. You may "
+"select from those options here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_update.html:17
+msgid "You may update the editable properties of your instance here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/detail.html:3
+#, fuzzy
+msgid "Instance Detail"
+msgstr "ID instancji:"
+
+#: dashboards/project/instances/templates/instances/update.html:3
+#: dashboards/project/instances/templates/instances/update.html:6
+msgid "Update Instance"
+msgstr "Aktualizuj instncję"
+
+#: dashboards/project/networks/tables.py:81
+msgid "Add Subnet"
+msgstr ""
+
+#: dashboards/project/networks/views.py:86
+#, fuzzy
+msgid "Unable to retrieve network details."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/networks/workflows.py:37
+msgid "Network Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:42
+msgid ""
+"From here you can create a new network.\n"
+"In addition a subnet associated with the network can be created in the next "
+"panel."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:56
+msgid "Subnet Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:61
+#: dashboards/project/networks/subnets/forms.py:48
+msgid "Network address in CIDR format (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:67
+msgid "Gateway IP (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:70
+#: dashboards/project/networks/subnets/forms.py:57
+#: dashboards/project/networks/subnets/forms.py:107
+msgid "IP address of Gateway (e.g. 192.168.0.1)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:77
+msgid ""
+"You can create a subnet associated with the new network, in which case "
+"\"Network Address\" must be specified. If you wish to create a network "
+"WITHOUT a subnet, uncheck the \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:89
+msgid "Specify \"Network Address\" or clear \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:94
+#: dashboards/project/networks/subnets/forms.py:70
+msgid "Network Address and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:98
+#: dashboards/project/networks/subnets/forms.py:74
+#: dashboards/project/networks/subnets/forms.py:119
+msgid "Gateway IP and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:112
+#, fuzzy
+msgid "Create"
+msgstr "Utwórz nowy wolumen."
+
+#: dashboards/project/networks/workflows.py:113
+#, python-format
+msgid "Created network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:114
+#, fuzzy, python-format
+msgid "Unable to create network \"%s\"."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/networks/workflows.py:130
+#, fuzzy, python-format
+msgid "Network \"%s\" was successfully created."
+msgstr "Klucz %s został pomyślnie usunięty."
+
+#: dashboards/project/networks/workflows.py:133
+#, fuzzy, python-format
+msgid "Failed to create network \"%s\"."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/networks/workflows.py:152
+#, fuzzy, python-format
+msgid "Subnet \"%s\" was successfully created."
+msgstr "Klucz %s został pomyślnie usunięty."
+
+#: dashboards/project/networks/workflows.py:155
+#, python-format
+msgid "Failed to create subnet \"%(sub)s\" for network \"%(net)s\"."
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+#, fuzzy
+msgid "Attached"
+msgstr "Dołącz wolumen"
+
+#: dashboards/project/networks/ports/tables.py:35
+#, fuzzy
+msgid "Detached"
+msgstr "Wolumeny"
+
+#: dashboards/project/networks/subnets/forms.py:85
+#, fuzzy, python-format
+msgid "Subnet %s was successfully created."
+msgstr "Klucz %s został pomyślnie usunięty."
+
+#: dashboards/project/networks/subnets/forms.py:90
+#, fuzzy, python-format
+msgid "Failed to create subnet %s"
+msgstr "Nie można utworzyć wolumenu: %s"
+
+#: dashboards/project/networks/subnets/forms.py:131
+#, fuzzy, python-format
+msgid "Subnet %s was successfully updated."
+msgstr "Klucz %s został pomyślnie usunięty."
+
+#: dashboards/project/networks/subnets/forms.py:136
+#, fuzzy, python-format
+msgid "Failed to update subnet %s"
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/project/networks/subnets/tabs.py:42
+#, fuzzy
+msgid "Unable to retrieve subnet details."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/networks/templates/networks/_detail_overview.html:3
+#, fuzzy
+msgid "Network Overview"
+msgstr "Instancje"
+
+#: dashboards/project/networks/templates/networks/detail.html:6
+#, fuzzy
+msgid "Network Detail: "
+msgstr "Wolumeny"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:3
+#, fuzzy
+msgid "Port Overview"
+msgstr "Instancje"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:17
+msgid "Fixed IP"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:21
+#, fuzzy
+msgid "IP address:"
+msgstr "Usuń projekt"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:22
+msgid "Subnet ID"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:28
+msgid "Mac Address"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/detail.html:3
+#: dashboards/project/networks/templates/networks/ports/detail.html:6
+#, fuzzy
+msgid "Port Detail"
+msgstr "Wolumeny"
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:3
+#, fuzzy
+msgid "Subnet Overview"
+msgstr "Instancje"
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:21
+msgid "IP allocation pool"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:24
+msgid "Start"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:25
+msgid " - End"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/detail.html:3
+#: dashboards/project/networks/templates/networks/subnets/detail.html:6
+#, fuzzy
+msgid "Subnet Detail"
+msgstr "Wolumeny"
+
+#: dashboards/project/volumes/forms.py:29
+msgid "Size (GB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:30
+msgid "Use snapshot as a source"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:49
+#, python-format
+msgid "Volume size must be equal to or greater than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:54
+#, fuzzy
+msgid "Unable to load the specified snapshot."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/project/volumes/forms.py:59
+#, fuzzy
+msgid "Choose a snapshot"
+msgstr "Wolumeny"
+
+#: dashboards/project/volumes/forms.py:83
+#, python-format
+msgid "The volume size cannot be less than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:92
+#, python-format
+msgid ""
+"A volume of %(req)iGB cannot be created as you only have %(avail)iGB of your "
+"quota available."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:99
+msgid "You are already using all of your available volumes."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:115
+#, fuzzy
+msgid "Unable to create volume."
+msgstr "Nie można utworzyć wolumenu: %s"
+
+#: dashboards/project/volumes/forms.py:123
+#, fuzzy
+msgid "Attach to Instance"
+msgstr "Uruchom obraz"
+
+#: dashboards/project/volumes/forms.py:124
+msgid "Select an instance to attach to."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:168
+msgid "Unknown instance (None)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:179
+#, python-format
+msgid "Attaching volume %(vol)s to instance %(inst)s on %(dev)s."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:188
+#, fuzzy
+msgid "Unable to attach volume."
+msgstr "Nie można dołączyć wolumenu: %s"
+
+#: dashboards/project/volumes/forms.py:212
+#, fuzzy, python-format
+msgid "Creating volume snapshot \"%s\""
+msgstr "tworzenie użytkownika %s..."
+
+#: dashboards/project/volumes/forms.py:218
+#, fuzzy
+msgid "Unable to create volume snapshot."
+msgstr "Nie można utworzyć wolumenu: %s"
+
+#: dashboards/project/volumes/tables.py:46
+#, fuzzy, python-format
+msgid "Unable to delete volume \"%s\". One or more snapshots depend on it."
+msgstr "Nie można utworzyć wolumenu: %s"
+
+#: dashboards/project/volumes/tables.py:66
+#, fuzzy
+msgid "Edit Attachments"
+msgstr "Dołącz wolumen"
+
+#: dashboards/project/volumes/tables.py:93
+#, python-format
+msgid "%sGB"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:106
+#: dashboards/project/volumes/views.py:149
+#, fuzzy
+msgid "Unable to retrieve attachment information."
+msgstr "Nie można wyrejestrować obrazu: %s"
+
+#: dashboards/project/volumes/tables.py:123
+#, fuzzy, python-format
+msgid "Attached to %(instance)s on %(dev)s"
+msgstr "Uruchom obraz"
+
+#: dashboards/project/volumes/tables.py:180
+msgid "Detach"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:181
+#, fuzzy
+msgid "Detaching"
+msgstr "Wolumeny"
+
+#: dashboards/project/volumes/tables.py:216
+#, python-format
+msgid "%(dev)s on instance %(instance_name)s"
+msgstr ""
+
+#: dashboards/project/volumes/tabs.py:42
+#, fuzzy
+msgid "Unable to retrieve volume details."
+msgstr "Nie można utworzyć wolumenu: %s"
+
+#: dashboards/project/volumes/views.py:50
+#, fuzzy
+msgid "Unable to retrieve volume list."
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/volumes/views.py:58
+#, fuzzy
+msgid "Unable to retrieve volume/instance attachment information"
+msgstr "Nie można cofnąć: %s"
+
+#: dashboards/project/volumes/views.py:130
+#: dashboards/project/volumes/views.py:140
+#, fuzzy
+msgid "Unable to retrieve volume information."
+msgstr "Nie można wyrejestrować obrazu: %s"
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:9
+#: dashboards/project/volumes/templates/volumes/attach.html:6
+msgid "Manage Volume Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:13
+#, fuzzy
+msgid "Attach To Instance"
+msgstr "Uruchom obraz"
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:22
+#, fuzzy
+msgid "Attach Volume"
+msgstr "Dołącz wolumen"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:20
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:18
+msgid "Volumes are block devices that can be attached to instances."
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:22
+#, fuzzy
+msgid "Volume Quotas"
+msgstr "Wolumeny"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:25
+msgid "Total Gigabytes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:34
+msgid "Number of Volumes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:8
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:23
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:3
+#, fuzzy
+msgid "Create Volume Snapshot"
+msgstr "Utwórz nowy wolumen."
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:3
+#, fuzzy
+msgid "Volume Overview"
+msgstr "Instancje"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:34
+#, fuzzy
+msgid "Attachments"
+msgstr "Dołącz wolumen"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:46
+#, fuzzy
+msgid "Not attached"
+msgstr "Dołącz wolumen"
+
+#: dashboards/project/volumes/templates/volumes/create.html:6
+#, fuzzy
+msgid "Create a Volume"
+msgstr "Utwórz nowy wolumen."
+
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:6
+msgid "Create a Volume Snapshot"
+msgstr ""
+
+#: dashboards/settings/dashboard.py:24 templates/_header.html:4
+msgid "Settings"
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:36 dashboards/settings/project/forms.py:36
+#, fuzzy
+msgid "Select a Project"
+msgstr "Usuń projekt"
+
+#: dashboards/settings/ec2/forms.py:46
+#, fuzzy
+msgid "Unable to retrieve tenant list."
+msgstr "Nie można utworzyć klucza: %s"
+
+#: dashboards/settings/ec2/forms.py:88
+#, fuzzy
+msgid "Unable to fetch EC2 credentials."
+msgstr "Wygeneruj dane uwierzytelniające x509."
+
+#: dashboards/settings/ec2/forms.py:101
+#, fuzzy, python-format
+msgid "Error writing zipfile: %(exc)s"
+msgstr "tworzenie użytkownika %s..."
+
+#: dashboards/settings/ec2/panel.py:25
+#, fuzzy
+msgid "EC2 Credentials"
+msgstr "Wyślij dane uwierzytelniające"
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:8
+#: dashboards/settings/ec2/templates/ec2/download_form.html:23
+#: dashboards/settings/ec2/templates/ec2/index.html:3
+#: dashboards/settings/ec2/templates/ec2/index.html:6
+#, fuzzy
+msgid "Download EC2 Credentials"
+msgstr "Wyślij dane uwierzytelniające"
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:18
+msgid ""
+"Clicking \"Download EC2 Credentials\" will download a zip file which "
+"includes an rc file with your access/secret keys, as well as your x509 "
+"private key and certificate."
+msgstr ""
+
+#: dashboards/settings/project/forms.py:71
+#, fuzzy, python-format
+msgid "Error Downloading RC File: %s"
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/settings/project/panel.py:25
+#: dashboards/settings/project/templates/project/_openrc.html:8
+#: dashboards/settings/project/templates/project/settings.html:3
+#: dashboards/settings/project/templates/project/settings.html:6
+msgid "OpenStack API"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:27
+#, fuzzy
+msgid "Service Name"
+msgstr "Obrazy"
+
+#: dashboards/settings/project/tables.py:29
+msgid "Service Endpoint"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:33
+msgid "API Endpoints"
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:15
+#, fuzzy
+msgid "Download OpenStack RC File"
+msgstr "Nie można zaktualizować obrazu: %s"
+
+#: dashboards/settings/project/templates/project/_openrc.html:25
+msgid ""
+"Download the RC file for the selected project, then type \"source openrc\" "
+"in the terminal to configure your environment to communicate with OpenStack."
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:30
+msgid "Download RC File"
+msgstr ""
+
+#: dashboards/settings/user/forms.py:57
+msgid "Settings saved."
+msgstr ""
+
+#: dashboards/settings/user/panel.py:25
+#: dashboards/settings/user/templates/user/_settings.html:8
+#: dashboards/settings/user/templates/user/settings.html:3
+#: dashboards/settings/user/templates/user/settings.html:6
+msgid "User Settings"
+msgstr ""
+
+#: dashboards/settings/user/templates/user/_settings.html:18
+#, fuzzy
+msgid "From here you can modify dashboard settings for your user."
+msgstr "Tutaj można zarządzać użytkownikami i rolami."
+
+#: templates/403.html:4 templates/403.html.py:9
+msgid "Forbidden"
+msgstr ""
+
+#: templates/403.html:20 templates/404.html:19 templates/500.html:19
+msgid "Home"
msgstr ""
#: templates/404.html:4
@@ -108,3 +3488,48 @@ msgid ""
"An unexpected error occurred while processing your request. Please try your "
"request again."
msgstr ""
+
+#: templates/_header.html:3
+msgid "Logged in as"
+msgstr ""
+
+#: templates/_header.html:6
+msgid "Help"
+msgstr ""
+
+#: templates/_header.html:8
+msgid "Sign Out"
+msgstr ""
+
+#: test/settings.py:50
+msgid "Password must be between 8 and 18 characters."
+msgstr ""
+
+#: usage/base.py:97
+#, fuzzy
+msgid "Unable to retrieve usage information."
+msgstr "Nie można wyrejestrować obrazu: %s"
+
+#: usage/base.py:100
+msgid "You are viewing data for the future, which may or may not exist."
+msgstr ""
+
+#: usage/tables.py:11
+msgid "Download CSV Summary"
+msgstr ""
+
+#: usage/tables.py:25
+msgid "VCPU Hours"
+msgstr ""
+
+#: usage/tables.py:32
+msgid "Disk GB Hours"
+msgstr ""
+
+#: usage/tables.py:40 usage/tables.py:68
+msgid "Usage Summary"
+msgstr ""
+
+#: usage/tables.py:60
+msgid "Uptime"
+msgstr ""
diff --git a/openstack_dashboard/locale/pt/LC_MESSAGES/django.mo b/openstack_dashboard/locale/pt/LC_MESSAGES/django.mo
index 73b42000b..f73f9f213 100644
--- a/openstack_dashboard/locale/pt/LC_MESSAGES/django.mo
+++ b/openstack_dashboard/locale/pt/LC_MESSAGES/django.mo
Binary files differ
diff --git a/openstack_dashboard/locale/pt/LC_MESSAGES/django.po b/openstack_dashboard/locale/pt/LC_MESSAGES/django.po
index 6a8dc72d5..56c684f14 100644
--- a/openstack_dashboard/locale/pt/LC_MESSAGES/django.po
+++ b/openstack_dashboard/locale/pt/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Horizon\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-09-18 22:18+0000\n"
+"POT-Creation-Date: 2012-10-05 19:30+0000\n"
"PO-Revision-Date: 2012-08-14 08:40+0000\n"
"Last-Translator: Gabriel Hurley <gabriel@strikeawe.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,63 +17,3273 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: settings.py:141
+#: settings.py:142
msgid "Bulgarian (Bulgaria)"
msgstr ""
-#: settings.py:142
+#: settings.py:143
msgid "Czech"
msgstr ""
-#: settings.py:143
+#: settings.py:144
msgid "English"
msgstr "Inglês"
-#: settings.py:144
+#: settings.py:145
msgid "Spanish"
msgstr "Espanhol"
-#: settings.py:145
+#: settings.py:146
msgid "French"
msgstr "Francês"
-#: settings.py:146
+#: settings.py:147
msgid "Italiano"
msgstr "Italiano"
-#: settings.py:147
+#: settings.py:148
msgid "Japanese"
msgstr "Japonês"
-#: settings.py:148
+#: settings.py:149
msgid "Korean (Korea)"
msgstr ""
-#: settings.py:149
+#: settings.py:150
msgid "Dutch (Netherlands)"
msgstr ""
-#: settings.py:150
+#: settings.py:151
msgid "Polish"
msgstr "Polonês"
-#: settings.py:151
+#: settings.py:152
msgid "Portuguese"
msgstr "Português"
-#: settings.py:152
+#: settings.py:153
#, fuzzy
msgid "Portuguese (Brazil)"
msgstr "Português"
-#: settings.py:153
+#: settings.py:154
msgid "Simplified Chinese"
msgstr "Chinês Simplificado"
-#: settings.py:154
+#: settings.py:155
msgid "Traditional Chinese"
msgstr "Chinês Tradicional"
+#: api/keystone.py:56
+#, python-format
+msgid "%(type)s (%(backend)s backend)"
+msgstr ""
+
+#: api/nova.py:191
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(group)s"
+msgstr "PERMITIR %(from)s:%(to)s de %(group)s"
+
+#: api/nova.py:196
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(cidr)s"
+msgstr "PERMITIR %(from)s:%(to)s de %(cidr)s"
+
+#: api/nova.py:532
+msgid "Unknown instance"
+msgstr ""
+
+#: api/swift.py:217
+msgid "Unicode is not currently supported for object copy."
+msgstr "Unicode não é suportado para cópia de objeto."
+
+#: dashboards/admin/dashboard.py:24
+msgid "System Panel"
+msgstr "Painel do Sistema"
+
+#: dashboards/admin/dashboard.py:30
+msgid "Admin"
+msgstr "Administração"
+
+#: dashboards/admin/flavors/forms.py:36 dashboards/admin/networks/forms.py:34
+#: dashboards/admin/networks/forms.py:69
+#: dashboards/admin/networks/ports/forms.py:40
+#: dashboards/admin/networks/ports/forms.py:72
+#: dashboards/admin/networks/ports/tables.py:73
+#: dashboards/admin/networks/subnets/tables.py:70
+#: dashboards/admin/projects/tables.py:87
+#: dashboards/admin/projects/workflows.py:71
+#: dashboards/admin/services/tables.py:38
+#: dashboards/admin/volumes/tables.py:10
+#: dashboards/project/access_and_security/security_groups/forms.py:36
+#: dashboards/project/access_and_security/security_groups/tables.py:58
+#: dashboards/project/images_and_snapshots/images/forms.py:40
+#: dashboards/project/images_and_snapshots/images/forms.py:115
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:9
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:10
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:77
+#: dashboards/project/instances/templates/instances/_detail_overview.html:9
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:9
+#: dashboards/project/networks/forms.py:37
+#: dashboards/project/networks/tables.py:94
+#: dashboards/project/networks/ports/tables.py:40
+#: dashboards/project/networks/subnets/forms.py:43
+#: dashboards/project/networks/subnets/forms.py:102
+#: dashboards/project/networks/subnets/tables.py:82
+#: dashboards/project/networks/templates/networks/_detail_overview.html:7
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:9
+#: dashboards/project/volumes/tables.py:144
+#: dashboards/project/volumes/tables.py:164
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:9
+msgid "Name"
+msgstr "Nome"
+
+#: dashboards/admin/flavors/forms.py:37 dashboards/admin/flavors/tables.py:41
+#: dashboards/admin/projects/workflows.py:39
+#: dashboards/project/instances/templates/instances/_detail_overview.html:26
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:10
+#: usage/tables.py:19
+msgid "VCPUs"
+msgstr "VCPUs"
+
+#: dashboards/admin/flavors/forms.py:38
+msgid "RAM MB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:39
+msgid "Root Disk GB"
+msgstr "Root Disco GB"
+
+#: dashboards/admin/flavors/forms.py:40
+msgid "Ephemeral Disk GB"
+msgstr "Disco Efêmero GB"
+
+#: dashboards/admin/flavors/forms.py:50
+msgid "Unable to get unique ID for new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:67
+#, python-format
+msgid "Created flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:71
+msgid "Unable to create flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:92
+#, python-format
+msgid "Updated flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:96
+msgid "Unable to update flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/panel.py:29 dashboards/admin/flavors/tables.py:15
+#: dashboards/admin/flavors/tables.py:52
+#: dashboards/admin/flavors/templates/flavors/index.html:3
+#: dashboards/admin/flavors/templates/flavors/index.html:6
+msgid "Flavors"
+msgstr "Sabors"
+
+#: dashboards/admin/flavors/tables.py:14
+#: dashboards/project/instances/workflows.py:177
+#: dashboards/project/instances/templates/instances/_detail_overview.html:22
+msgid "Flavor"
+msgstr "Sabor"
+
+#: dashboards/admin/flavors/tables.py:23
+#: dashboards/admin/flavors/templates/flavors/_create.html:8
+#: dashboards/admin/flavors/templates/flavors/_create.html:23
+#: dashboards/admin/flavors/templates/flavors/create.html:3
+#: dashboards/admin/flavors/templates/flavors/create.html:6
+msgid "Create Flavor"
+msgstr "Criar um Sabor"
+
+#: dashboards/admin/flavors/tables.py:30
+#: dashboards/admin/flavors/templates/flavors/_edit.html:8
+#: dashboards/admin/flavors/templates/flavors/edit.html:3
+#: dashboards/admin/flavors/templates/flavors/edit.html:6
+msgid "Edit Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:36
+#, python-format
+msgid "%sMB"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:40
+msgid "Flavor Name"
+msgstr "Nome Sabor"
+
+#: dashboards/admin/flavors/tables.py:43
+#: dashboards/project/instances/templates/instances/_detail_overview.html:24
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: usage/tables.py:22
+msgid "RAM"
+msgstr "RAM"
+
+#: dashboards/admin/flavors/tables.py:45
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+msgid "Root Disk"
+msgstr "Disco Root"
+
+#: dashboards/admin/flavors/tables.py:47
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+msgid "Ephemeral Disk"
+msgstr "Disco Efêmero"
+
+#: dashboards/admin/flavors/views.py:49
+msgid "Unable to retrieve flavor list."
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:76
+msgid "Unable to retrieve flavor data."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:17
+#: dashboards/admin/flavors/templates/flavors/_edit.html:17
+#: dashboards/admin/images/templates/images/_update.html:17
+#: dashboards/admin/networks/templates/networks/_create.html:17
+#: dashboards/admin/networks/templates/networks/ports/_create.html:17
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:17
+#: dashboards/admin/projects/tables.py:89
+#: dashboards/admin/projects/workflows.py:74
+#: dashboards/admin/projects/templates/projects/_add_user.html:17
+#: dashboards/admin/projects/templates/projects/_create.html:17
+#: dashboards/admin/projects/templates/projects/_create_user.html:17
+#: dashboards/admin/projects/templates/projects/_quotas.html:16
+#: dashboards/admin/projects/templates/projects/_update.html:17
+#: dashboards/admin/users/templates/users/_create.html:16
+#: dashboards/admin/users/templates/users/_update.html:16
+#: dashboards/project/access_and_security/security_groups/forms.py:38
+#: dashboards/project/access_and_security/security_groups/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:17
+#: dashboards/project/containers/templates/containers/_copy.html:16
+#: dashboards/project/containers/templates/containers/_create.html:16
+#: dashboards/project/containers/templates/containers/_upload.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/_create.html:16
+#: dashboards/project/networks/templates/networks/subnets/_create.html:17
+#: dashboards/project/volumes/forms.py:28
+#: dashboards/project/volumes/forms.py:195
+#: dashboards/project/volumes/tables.py:147
+#: dashboards/project/volumes/templates/volumes/_create.html:18
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:17
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:14
+msgid "Description"
+msgstr "Descrição"
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:18
+msgid "From here you can define the sizing of a new flavor."
+msgstr "A partir daí você pode definir o tamanho de um novo sabor."
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:24
+#: dashboards/admin/flavors/templates/flavors/_edit.html:25
+#: dashboards/admin/images/templates/images/_update.html:24
+#: dashboards/admin/networks/templates/networks/_create.html:24
+#: dashboards/admin/networks/templates/networks/_update.html:23
+#: dashboards/admin/networks/templates/networks/ports/_create.html:24
+#: dashboards/admin/networks/templates/networks/ports/_update.html:28
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:24
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:32
+#: dashboards/admin/projects/templates/projects/_add_user.html:24
+#: dashboards/admin/projects/templates/projects/_create.html:24
+#: dashboards/admin/projects/templates/projects/_create_user.html:24
+#: dashboards/admin/projects/templates/projects/_quotas.html:23
+#: dashboards/admin/projects/templates/projects/_update.html:24
+#: dashboards/admin/users/templates/users/_create.html:23
+#: dashboards/admin/users/templates/users/_update.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:32
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:20
+#: dashboards/project/containers/templates/containers/_copy.html:23
+#: dashboards/project/containers/templates/containers/_create.html:23
+#: dashboards/project/containers/templates/containers/_upload.html:24
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:32
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:24
+#: dashboards/project/instances/templates/instances/_update.html:23
+#: dashboards/project/networks/templates/networks/_create.html:23
+#: dashboards/project/networks/templates/networks/_update.html:23
+#: dashboards/project/networks/templates/networks/subnets/_create.html:24
+#: dashboards/project/networks/templates/networks/subnets/_update.html:32
+#: dashboards/project/volumes/templates/volumes/_attach.html:24
+#: dashboards/project/volumes/templates/volumes/_create.html:56
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:24
+#: dashboards/settings/ec2/templates/ec2/download_form.html:24
+#: dashboards/settings/project/templates/project/_openrc.html:31
+#: dashboards/settings/user/templates/user/_settings.html:24
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:18
+msgid "From here you can alter the sizing of the current flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:19
+msgid ""
+"Note: this will not affect the resources allocated to any existing instances "
+"using this flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:24
+#: dashboards/admin/projects/workflows.py:270
+#: dashboards/settings/user/templates/user/_settings.html:23
+msgid "Save"
+msgstr "Guardar"
+
+#: dashboards/admin/images/panel.py:29 dashboards/admin/images/tables.py:44
+#: dashboards/admin/images/templates/images/index.html:3
+#: dashboards/admin/images/templates/images/index.html:6
+#: dashboards/project/images_and_snapshots/images/tables.py:47
+#: dashboards/project/images_and_snapshots/images/tables.py:132
+msgid "Images"
+msgstr "Imagens"
+
+#: dashboards/admin/images/tables.py:40
+#: dashboards/project/images_and_snapshots/images/tables.py:113
+#: dashboards/project/instances/templates/instances/_detail_overview.html:74
+msgid "Image Name"
+msgstr "Nome de Imagen"
+
+#: dashboards/admin/images/views.py:55
+msgid "Unable to retrieve image list."
+msgstr "Não foi possível recuperar a lista de imagem."
+
+#: dashboards/admin/images/templates/images/_update.html:8
+#: dashboards/admin/images/templates/images/_update.html:23
+#: dashboards/admin/images/templates/images/update.html:4
+#: dashboards/admin/images/templates/images/update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:22
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:6
+msgid "Update Image"
+msgstr "Atualizar Imagem"
+
+#: dashboards/admin/images/templates/images/_update.html:18
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:17
+msgid "From here you can modify different properties of an image."
+msgstr ""
+"A partir daqui você pode modificar diferentes propriedades de uma imagem."
+
+#: dashboards/admin/instances/panel.py:29
+#: dashboards/admin/instances/tables.py:94
+#: dashboards/admin/instances/templates/instances/index.html:3
+#: dashboards/admin/projects/workflows.py:40
+#: dashboards/project/instances/panel.py:25
+#: dashboards/project/instances/tables.py:70
+#: dashboards/project/instances/tables.py:90
+#: dashboards/project/instances/tables.py:107
+#: dashboards/project/instances/tables.py:136
+#: dashboards/project/instances/tables.py:313
+#: dashboards/project/instances/templates/instances/index.html:3
+#: dashboards/project/instances/templates/instances/index.html:6
+msgid "Instances"
+msgstr "Instâncias"
+
+#: dashboards/admin/instances/tables.py:60 usage/tables.py:30
+msgid "Project Name"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:67
+#: dashboards/admin/services/tables.py:40
+msgid "Host"
+msgstr "Hospedeiro"
+
+#: dashboards/admin/instances/tables.py:71
+#: dashboards/project/instances/tables.py:290
+#: dashboards/project/instances/workflows.py:176 usage/tables.py:57
+msgid "Instance Name"
+msgstr "Nome de Instância"
+
+#: dashboards/admin/instances/tables.py:72
+#: dashboards/project/access_and_security/floating_ips/tables.py:111
+#: dashboards/project/access_and_security/floating_ips/workflows.py:32
+#: dashboards/project/access_and_security/floating_ips/workflows.py:39
+#: dashboards/project/instances/tables.py:291
+msgid "IP Address"
+msgstr "Endereço IP"
+
+#: dashboards/admin/instances/tables.py:74
+#: dashboards/project/containers/tables.py:256
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:30
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:37
+#: dashboards/project/instances/tables.py:293
+#: dashboards/project/volumes/tables.py:150
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:26
+msgid "Size"
+msgstr "Tamanho"
+
+#: dashboards/admin/instances/tables.py:79
+#: dashboards/admin/networks/tables.py:74
+#: dashboards/admin/networks/ports/tables.py:77
+#: dashboards/project/images_and_snapshots/images/tables.py:119
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:13
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:18
+#: dashboards/project/instances/tables.py:298
+#: dashboards/project/instances/templates/instances/_detail_overview.html:13
+#: dashboards/project/networks/tables.py:100
+#: dashboards/project/networks/ports/tables.py:44
+#: dashboards/project/networks/templates/networks/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:30
+#: dashboards/project/volumes/tables.py:154
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:17
+msgid "Status"
+msgstr "Condição"
+
+#: dashboards/admin/instances/tables.py:83
+#: dashboards/project/instances/tables.py:302
+msgid "Task"
+msgstr "Tarefa"
+
+#: dashboards/admin/instances/tables.py:90
+#: dashboards/project/instances/tables.py:309
+msgid "Power State"
+msgstr "Poder Estado"
+
+#: dashboards/admin/instances/views.py:49
+#: dashboards/project/access_and_security/views.py:76
+#: dashboards/project/access_and_security/floating_ips/workflows.py:65
+msgid "Unable to retrieve instance list."
+msgstr "Não foi possível recuperar a lista de instâncias."
+
+#: dashboards/admin/instances/views.py:63
+#: dashboards/admin/networks/views.py:48
+msgid "Unable to retrieve instance tenant information."
+msgstr "Não é possível recuperar informações projeto instâncias."
+
+#: dashboards/admin/instances/views.py:80
+#: dashboards/project/instances/views.py:82
+msgid "Unable to retrieve instance size information."
+msgstr "Não é possível recuperar informações de tamanho instância."
+
+#: dashboards/admin/instances/templates/instances/index.html:6
+msgid "All Instances"
+msgstr "Todas as Instâncias"
+
+#: dashboards/admin/networks/forms.py:36
+#: dashboards/admin/networks/tables.py:67
+#: dashboards/admin/projects/tables.py:65 dashboards/project/dashboard.py:40
+#: dashboards/project/instances/workflows.py:38
+msgid "Project"
+msgstr "Projeto"
+
+#: dashboards/admin/networks/forms.py:37 dashboards/admin/networks/forms.py:74
+#: dashboards/admin/networks/tables.py:72
+#: dashboards/project/networks/tables.py:98
+#: dashboards/project/networks/templates/networks/_detail_overview.html:17
+msgid "Shared"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:46 dashboards/admin/users/forms.py:42
+msgid "Select a project"
+msgstr "Selecione um projeto."
+
+#: dashboards/admin/networks/forms.py:58
+#, python-format
+msgid "Network %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:64
+#, python-format
+msgid "Failed to create network %s"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:71
+#: dashboards/admin/networks/templates/networks/ports/_update.html:12
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:12
+#: dashboards/admin/users/forms.py:114
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:11
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:12
+#: dashboards/project/instances/templates/instances/_detail_overview.html:11
+#: dashboards/project/networks/forms.py:39
+#: dashboards/project/networks/templates/networks/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_update.html:12
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:11
+msgid "ID"
+msgstr "ID"
+
+#: dashboards/admin/networks/forms.py:82
+#: dashboards/project/networks/forms.py:48
+#, python-format
+msgid "Network %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:87
+#: dashboards/project/networks/forms.py:53
+#, python-format
+msgid "Failed to update network %s"
+msgstr ""
+
+#: dashboards/admin/networks/panel.py:25
+#: dashboards/admin/networks/tables.py:35
+#: dashboards/admin/networks/tables.py:80
+#: dashboards/admin/networks/templates/networks/index.html:3
+#: dashboards/admin/networks/templates/networks/index.html:6
+#: dashboards/project/instances/workflows.py:412
+#: dashboards/project/networks/panel.py:25
+#: dashboards/project/networks/tables.py:44
+#: dashboards/project/networks/tables.py:106
+#: dashboards/project/networks/templates/networks/index.html:3
+#: dashboards/project/networks/templates/networks/index.html:6
+msgid "Networks"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:34
+#: dashboards/project/networks/tables.py:43
+#: dashboards/project/networks/templates/networks/subnets/index.html:3
+#: dashboards/project/networks/templates/networks/subnets/index.html:6
+msgid "Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:41
+#: dashboards/project/networks/tables.py:59
+#, python-format
+msgid "Failed to delete network %s"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:49
+#: dashboards/admin/networks/templates/networks/_create.html:8
+#: dashboards/admin/networks/templates/networks/_create.html:23
+#: dashboards/admin/networks/templates/networks/create.html:3
+#: dashboards/admin/networks/templates/networks/create.html:6
+#: dashboards/project/networks/tables.py:67
+#: dashboards/project/networks/workflows.py:111
+#: dashboards/project/networks/templates/networks/_create.html:7
+#: dashboards/project/networks/templates/networks/_create.html:22
+#: dashboards/project/networks/templates/networks/create.html:3
+#: dashboards/project/networks/templates/networks/create.html:6
+msgid "Create Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:56
+#: dashboards/admin/networks/templates/networks/_update.html:7
+#: dashboards/project/networks/tables.py:74
+#: dashboards/project/networks/templates/networks/_update.html:7
+msgid "Edit Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:68
+#: dashboards/admin/networks/ports/forms.py:33
+#: dashboards/project/networks/subnets/forms.py:35
+msgid "Network Name"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:71
+#: dashboards/project/networks/tables.py:97
+msgid "Subnets Associated"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:76
+#: dashboards/admin/networks/ports/tables.py:79
+#: dashboards/project/networks/tables.py:102
+#: dashboards/project/networks/ports/tables.py:46
+#: dashboards/project/networks/templates/networks/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:32
+msgid "Admin State"
+msgstr ""
+
+#: dashboards/admin/networks/views.py:60
+#: dashboards/project/networks/views.py:52
+msgid "Network list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:91
+#: dashboards/project/networks/views.py:109
+msgid "Subnet list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:103
+#: dashboards/project/networks/views.py:121
+msgid "Port list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:118
+#: dashboards/project/networks/views.py:134
+#: dashboards/project/networks/subnets/tables.py:96
+#, python-format
+msgid "Unable to retrieve details for network \"%s\"."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:36
+#: dashboards/project/networks/subnets/forms.py:39
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:13
+msgid "Network ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:42
+#: dashboards/admin/networks/ports/forms.py:74
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:34
+msgid "Device ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:54
+#, python-format
+msgid "Port %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:59
+#, python-format
+msgid "Failed to create a port for network %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:84
+#, python-format
+msgid "Port %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:89
+#, python-format
+msgid "Failed to update port %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:34
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:6
+msgid "Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:35
+#: dashboards/admin/networks/ports/tables.py:83
+#: dashboards/project/networks/ports/tables.py:53
+msgid "Ports"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:41
+#: dashboards/admin/networks/subnets/tables.py:39
+#: dashboards/project/networks/subnets/tables.py:51
+#, python-format
+msgid "Failed to delete subnet %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:51
+#: dashboards/admin/networks/templates/networks/ports/_create.html:8
+#: dashboards/admin/networks/templates/networks/ports/_create.html:23
+#: dashboards/admin/networks/templates/networks/ports/create.html:3
+#: dashboards/admin/networks/templates/networks/ports/create.html:6
+msgid "Create Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:62
+#: dashboards/admin/networks/templates/networks/ports/_update.html:7
+msgid "Edit Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:75
+#: dashboards/project/networks/ports/tables.py:42
+msgid "Fixed IPs"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:76
+#: dashboards/project/networks/ports/tables.py:43
+msgid "Device Attached"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tabs.py:32
+#: dashboards/admin/overview/panel.py:29
+#: dashboards/admin/overview/templates/overview/usage.html:6
+#: dashboards/project/images_and_snapshots/images/tabs.py:27
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:27
+#: dashboards/project/instances/tabs.py:26
+#: dashboards/project/networks/ports/tabs.py:32
+#: dashboards/project/networks/subnets/tabs.py:32
+#: dashboards/project/overview/panel.py:29
+#: dashboards/project/overview/templates/overview/usage.html:6
+#: dashboards/project/volumes/tabs.py:27
+msgid "Overview"
+msgstr "Visão Global"
+
+#: dashboards/admin/networks/ports/tabs.py:42
+#: dashboards/project/networks/ports/tabs.py:42
+msgid "Unable to retrieve port details."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:49
+#: dashboards/admin/networks/subnets/views.py:49
+#: dashboards/project/networks/subnets/views.py:54
+msgid "Unable to retrieve network."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:82
+msgid "Unable to retrieve port details"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/forms.py:43
+#, python-format
+msgid "Failed to retrieve network %s for a subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:32
+#: dashboards/project/networks/subnets/tables.py:44
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:6
+msgid "Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:33
+#: dashboards/admin/networks/subnets/tables.py:81
+#: dashboards/project/networks/subnets/tables.py:45
+#: dashboards/project/networks/subnets/tables.py:104
+msgid "Subnets"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:49
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:8
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:23
+#: dashboards/admin/networks/templates/networks/subnets/create.html:3
+#: dashboards/admin/networks/templates/networks/subnets/create.html:6
+#: dashboards/project/networks/workflows.py:53
+#: dashboards/project/networks/subnets/tables.py:61
+#: dashboards/project/networks/templates/networks/subnets/_create.html:8
+#: dashboards/project/networks/templates/networks/subnets/_create.html:23
+#: dashboards/project/networks/templates/networks/subnets/create.html:3
+#: dashboards/project/networks/templates/networks/subnets/create.html:6
+msgid "Create Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:60
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:7
+#: dashboards/project/networks/subnets/tables.py:72
+#: dashboards/project/networks/templates/networks/subnets/_update.html:7
+msgid "Edit Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:72
+#: dashboards/project/access_and_security/security_groups/forms.py:91
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:15
+msgid "CIDR"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:73
+#: dashboards/project/networks/workflows.py:66
+#: dashboards/project/networks/subnets/forms.py:53
+#: dashboards/project/networks/subnets/tables.py:85
+msgid "IP Version"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:74
+#: dashboards/project/networks/subnets/forms.py:54
+#: dashboards/project/networks/subnets/forms.py:104
+#: dashboards/project/networks/subnets/tables.py:86
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:19
+msgid "Gateway IP"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/views.py:82
+#: dashboards/project/networks/subnets/views.py:86
+msgid "Unable to retrieve subnet details"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_create.html:18
+#: dashboards/project/networks/templates/networks/_create.html:17
+msgid "Select a name for your network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:16
+#: dashboards/admin/networks/templates/networks/ports/_update.html:21
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:25
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:17
+#: dashboards/project/instances/templates/instances/_update.html:16
+#: dashboards/project/networks/templates/networks/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_update.html:25
+#: dashboards/settings/ec2/templates/ec2/download_form.html:17
+#: dashboards/settings/project/templates/project/_openrc.html:24
+#: dashboards/settings/user/templates/user/_settings.html:17
+msgid "Description:"
+msgstr "Descrição:"
+
+#: dashboards/admin/networks/templates/networks/_update.html:17
+#: dashboards/project/networks/templates/networks/_update.html:17
+msgid "You may update the editable properties of your network here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:22
+#: dashboards/admin/networks/templates/networks/ports/_update.html:27
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:31
+#: dashboards/project/instances/templates/instances/_update.html:22
+#: dashboards/project/networks/templates/networks/_update.html:22
+#: dashboards/project/networks/templates/networks/subnets/_update.html:31
+msgid "Save Changes"
+msgstr "Salvar as Alterações"
+
+#: dashboards/admin/networks/templates/networks/update.html:3
+#: dashboards/admin/networks/templates/networks/update.html:6
+#: dashboards/project/networks/templates/networks/update.html:3
+#: dashboards/project/networks/templates/networks/update.html:6
+msgid "Update Network"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_create.html:18
+msgid ""
+"You can create a port for the network. If you specify device ID to be "
+"attached, the device specified will be attached to the port created."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_update.html:22
+msgid "You may update the editable properties of your port here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/update.html:3
+#: dashboards/admin/networks/templates/networks/ports/update.html:6
+msgid "Update Port"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:18
+#: dashboards/project/networks/templates/networks/subnets/_create.html:18
+msgid ""
+"You can create a subnet for the network. Any network address can be "
+"specified unless the network address does not overlap other subnets in the "
+"network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:14
+#: dashboards/project/networks/workflows.py:58
+#: dashboards/project/networks/subnets/forms.py:45
+#: dashboards/project/networks/subnets/tables.py:84
+#: dashboards/project/networks/templates/networks/subnets/_update.html:14
+msgid "Network Address"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:17
+#: dashboards/project/networks/templates/networks/subnets/_update.html:16
+msgid "IP version"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:26
+#: dashboards/project/networks/templates/networks/subnets/_update.html:26
+msgid "You may update the editable properties of your subnet here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/index.html:3
+#: dashboards/admin/networks/templates/networks/subnets/index.html:6
+#: dashboards/project/networks/templates/networks/detail.html:3
+msgid "Network Detail"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/update.html:3
+#: dashboards/admin/networks/templates/networks/subnets/update.html:6
+#: dashboards/project/networks/templates/networks/subnets/update.html:3
+#: dashboards/project/networks/templates/networks/subnets/update.html:6
+msgid "Update Subnet"
+msgstr ""
+
+#: dashboards/admin/overview/templates/overview/usage.html:3
+msgid "Usage Overview"
+msgstr "Visão geral do uso"
+
+#: dashboards/admin/overview/templates/overview/usage.html:12
+msgid "Monitoring"
+msgstr "Monitoramento"
+
+#: dashboards/admin/projects/panel.py:29
+#: dashboards/admin/projects/tables.py:66
+#: dashboards/admin/projects/tables.py:95
+#: dashboards/admin/projects/templates/projects/index.html:8
+#: templates/403.html:24 templates/404.html:23 templates/500.html:23
+msgid "Projects"
+msgstr "Projetos"
+
+#: dashboards/admin/projects/tables.py:19
+msgid "Modify Users"
+msgstr "Modificar os Usuários"
+
+#: dashboards/admin/projects/tables.py:32
+msgid "View Usage"
+msgstr "Ver Uso"
+
+#: dashboards/admin/projects/tables.py:39
+#: dashboards/admin/projects/templates/projects/_create.html:8
+#: dashboards/admin/projects/templates/projects/_create.html:23
+#: dashboards/admin/projects/templates/projects/create.html:6
+msgid "Create Project"
+msgstr "Criar projeto"
+
+#: dashboards/admin/projects/tables.py:46
+#: dashboards/admin/projects/workflows.py:269
+#: dashboards/admin/projects/templates/projects/update.html:3
+#: dashboards/admin/projects/templates/projects/update.html:6
+msgid "Edit Project"
+msgstr "Editar a Projeto"
+
+#: dashboards/admin/projects/tables.py:90
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:60
+#: dashboards/project/networks/templates/networks/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:15
+msgid "Project ID"
+msgstr "ID de Projeto"
+
+#: dashboards/admin/projects/tables.py:91
+#: dashboards/admin/projects/workflows.py:76
+#: dashboards/admin/projects/workflows.py:251
+#: dashboards/admin/services/tables.py:42 dashboards/admin/users/tables.py:40
+#: dashboards/admin/users/tables.py:115
+msgid "Enabled"
+msgstr "Ativado"
+
+#: dashboards/admin/projects/tables.py:104
+msgid "Remove"
+msgstr "Remover"
+
+#: dashboards/admin/projects/tables.py:105
+msgid "Removed"
+msgstr "Removido"
+
+#: dashboards/admin/projects/tables.py:106 dashboards/admin/users/tables.py:41
+#: dashboards/admin/users/tables.py:75
+#: dashboards/project/instances/workflows.py:39
+msgid "User"
+msgstr "Usuário"
+
+#: dashboards/admin/projects/tables.py:107 dashboards/admin/users/panel.py:29
+#: dashboards/admin/users/tables.py:42 dashboards/admin/users/tables.py:76
+#: dashboards/admin/users/tables.py:122
+#: dashboards/admin/users/templates/users/index.html:8
+msgid "Users"
+msgstr "Usuários"
+
+#: dashboards/admin/projects/tables.py:125
+msgid "Unable to retrieve role information."
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:130
+msgid "Roles"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:134
+msgid "Users For Project"
+msgstr "Para os usuários do Projeto"
+
+#: dashboards/admin/projects/tables.py:142
+msgid "Add To Project"
+msgstr "Adicionar ao Projeto"
+
+#: dashboards/admin/projects/tables.py:154
+msgid "Add New Users"
+msgstr "Adicionar novos usuários"
+
+#: dashboards/admin/projects/views.py:67
+msgid "Unable to retrieve project information."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:87
+msgid "Unable to retrieve project list."
+msgstr "Não é possível recuperar lista de projetos."
+
+#: dashboards/admin/projects/views.py:110
+msgid "Unable to retrieve users."
+msgstr "Não é possível recuperar os usuários."
+
+#: dashboards/admin/projects/views.py:154
+msgid "Unable to retrieve default quota values."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:182
+msgid "Unable to retrieve project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:37
+msgid "Injected File Content Bytes"
+msgstr "Bytes de Conteúdo Injetados Arquivo"
+
+#: dashboards/admin/projects/workflows.py:38
+msgid "Metadata Items"
+msgstr "Itens de Metadados"
+
+#: dashboards/admin/projects/workflows.py:41
+msgid "Injected Files"
+msgstr "Arquivos Injetados"
+
+#: dashboards/admin/projects/workflows.py:44
+#: dashboards/admin/volumes/panel.py:9 dashboards/admin/volumes/tables.py:15
+#: dashboards/admin/volumes/templates/volumes/index.html:3
+#: dashboards/admin/volumes/templates/volumes/index.html:6
+#: dashboards/project/volumes/panel.py:25
+#: dashboards/project/volumes/tables.py:38
+#: dashboards/project/volumes/tables.py:171
+#: dashboards/project/volumes/tables.py:183
+#: dashboards/project/volumes/templates/volumes/index.html:3
+#: dashboards/project/volumes/templates/volumes/index.html:6
+msgid "Volumes"
+msgstr "Volumes"
+
+#: dashboards/admin/projects/workflows.py:45
+msgid "Gigabytes"
+msgstr "Gigabytes"
+
+#: dashboards/admin/projects/workflows.py:46
+msgid "RAM (MB)"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:47
+#: dashboards/project/access_and_security/floating_ips/tables.py:50
+#: dashboards/project/access_and_security/floating_ips/tables.py:128
+msgid "Floating IPs"
+msgstr "IPs Flutuantes"
+
+#: dashboards/admin/projects/workflows.py:50
+msgid "Quota"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:52
+msgid "From here you can set quotas (max limits) for the project."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:81
+#: dashboards/admin/projects/workflows.py:254
+msgid "Project Info"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:82
+#: dashboards/admin/projects/templates/projects/_create.html:18
+msgid "From here you can create a new project to organize users."
+msgstr ""
+"A partir daí você pode criar um novo projeto para organizar os usuários."
+
+#: dashboards/admin/projects/workflows.py:101
+msgid "Unable to retrieve user list. Please try again later."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:155
+#: dashboards/admin/projects/templates/projects/_update_members.html:16
+msgid "Project Members"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:169
+#: dashboards/admin/users/views.py:47
+msgid "Unable to retrieve user list."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:180
+msgid "Add Project"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:181
+msgid "Finish"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:182
+#, python-format
+msgid "Created new project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:183
+#, python-format
+msgid "Unable to create project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:227
+#, python-format
+msgid "Failed to add %s project members and set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:246
+msgid "Unable to set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:256
+msgid "From here you can edit the project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:271
+#, python-format
+msgid "Modified project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:272
+#, python-format
+msgid "Unable to modify project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:342
+#, python-format
+msgid "Failed to modify %s project members and update project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:363
+msgid ""
+"Modified project information and members, but unable to modify project "
+"quotas."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:8
+#: dashboards/admin/projects/templates/projects/add_user.html:3
+#: dashboards/admin/projects/templates/projects/add_user.html:6
+msgid "Add User To Project"
+msgstr "Adicionar usuário ao projeto"
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:18
+msgid "Select the user role for the project."
+msgstr "Selecione a função do usuário para o projeto."
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:23
+msgid "Add"
+msgstr "Adicionar"
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:7
+#, python-format
+msgid "Create User for project '%(tenant_name)s'."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:18
+msgid "From here you can create a new user to add to this project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:23
+#: dashboards/admin/users/tables.py:20
+#: dashboards/admin/users/templates/users/_create.html:7
+#: dashboards/admin/users/templates/users/_create.html:22
+#: dashboards/admin/users/templates/users/create.html:7
+msgid "Create User"
+msgstr "Criar um Usuário"
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:7
+#: dashboards/admin/projects/templates/projects/_quotas.html:22
+msgid "Update Quota"
+msgstr "Atualize Cota"
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:17
+#, python-format
+msgid ""
+"From here you can edit quotas (max limits) for the project %(tenant.name)s."
+msgstr ""
+"A partir daí você pode editar cotas (limites máximos) para o projeto "
+"%(tenant.name)s."
+
+#: dashboards/admin/projects/templates/projects/_update.html:8
+#: dashboards/admin/projects/templates/projects/_update.html:23
+#: dashboards/admin/projects/templates/projects/quotas.html:6
+msgid "Update Project"
+msgstr "Atualização do Projeto"
+
+#: dashboards/admin/projects/templates/projects/_update.html:18
+msgid "From here you can edit a project."
+msgstr "A partir daí você pode editar um projeto."
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:7
+msgid ""
+"From here you can add and remove members to this project from the list of "
+"all available users."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:10
+msgid "All Users"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:25
+#: dashboards/admin/projects/templates/projects/_update_members.html:32
+msgid "No users found."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/create_user.html:3
+#: dashboards/admin/projects/templates/projects/create_user.html:6
+msgid "Add New User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:3
+msgid "Project Usage Overview"
+msgstr "Visão geral do uso do Projeto"
+
+#: dashboards/admin/projects/templates/projects/usage.html:7
+msgid "Project Usage"
+msgstr "Uso do Projeto"
+
+#: dashboards/admin/projects/templates/projects/users.html:7
+msgid "Users for Project"
+msgstr "Usuários para o Projeto"
+
+#: dashboards/admin/quotas/panel.py:29 dashboards/admin/quotas/tables.py:36
+msgid "Quotas"
+msgstr "Cotas"
+
+#: dashboards/admin/quotas/tables.py:28
+msgid "Quota Name"
+msgstr "Nome Cota"
+
+#: dashboards/admin/quotas/tables.py:29
+msgid "Limit"
+msgstr "Limite"
+
+#: dashboards/admin/quotas/views.py:46
+msgid "Unable to get quota info."
+msgstr "Não foi possível obter informação de cota."
+
+#: dashboards/admin/quotas/templates/quotas/index.html:8
+msgid "Default Quotas"
+msgstr "Cotas Padrão"
+
+#: dashboards/admin/services/panel.py:29
+#: dashboards/admin/services/tables.py:47
+#: dashboards/admin/services/templates/services/index.html:8
+msgid "Services"
+msgstr "Serviços"
+
+#: dashboards/admin/services/tables.py:37
+msgid "Id"
+msgstr "Id"
+
+#: dashboards/admin/services/tables.py:39
+msgid "Service"
+msgstr "Serviço"
+
+#: dashboards/admin/users/forms.py:54
+msgid "Passwords do not match."
+msgstr "As senhas não coincidem."
+
+#: dashboards/admin/users/forms.py:62 dashboards/admin/users/forms.py:115
+#: dashboards/admin/users/tables.py:108
+msgid "User Name"
+msgstr "Nome de Usuário"
+
+#: dashboards/admin/users/forms.py:63 dashboards/admin/users/forms.py:116
+#: dashboards/admin/users/tables.py:109
+msgid "Email"
+msgstr "E-mail"
+
+#: dashboards/admin/users/forms.py:65 dashboards/admin/users/forms.py:117
+msgid "Password"
+msgstr "Senha"
+
+#: dashboards/admin/users/forms.py:70 dashboards/admin/users/forms.py:124
+msgid "Confirm Password"
+msgstr "Confirmar a Senha"
+
+#: dashboards/admin/users/forms.py:73 dashboards/admin/users/forms.py:127
+msgid "Primary Project"
+msgstr "Projeto Principal"
+
+#: dashboards/admin/users/forms.py:75
+msgid "Role"
+msgstr "Função"
+
+#: dashboards/admin/users/forms.py:96
+#, python-format
+msgid "User \"%s\" was successfully created."
+msgstr "\"%s\" usuário foi criado com sucesso."
+
+#: dashboards/admin/users/forms.py:106
+msgid "Unable to add userto primary project."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:110
+msgid "Unable to create user."
+msgstr "Incapaz de criar o usuário."
+
+#: dashboards/admin/users/forms.py:151
+msgid "name"
+msgstr "nome"
+
+#: dashboards/admin/users/forms.py:151
+msgid "email"
+msgstr "e-mail"
+
+#: dashboards/admin/users/forms.py:160
+msgid "primary project"
+msgstr "projeto principal"
+
+#: dashboards/admin/users/forms.py:173
+#, python-format
+msgid "The user %s has no role defined for"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:181
+msgid "password"
+msgstr "senha"
+
+#: dashboards/admin/users/forms.py:190
+msgid "User has been updated successfully."
+msgstr "Usuário foi atualizado com sucesso."
+
+#: dashboards/admin/users/forms.py:194
+#, python-format
+msgid "Unable to update %(attributes)s for the user."
+msgstr "Não é possível atualizar a %(attributes)s para o usuário"
+
+#: dashboards/admin/users/tables.py:32
+#: dashboards/project/images_and_snapshots/images/tables.py:68
+msgid "Edit"
+msgstr "Editar"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Enable"
+msgstr "Ativar"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Disable"
+msgstr "Desativar"
+
+#: dashboards/admin/users/tables.py:40
+msgid "Disabled"
+msgstr "Desativado"
+
+#: dashboards/admin/users/tables.py:63
+msgid "You cannot disable the user you are currently logged in as."
+msgstr "Não é possível recuperar lista de usuários."
+
+#: dashboards/admin/users/tables.py:114
+msgid "User ID"
+msgstr ""
+
+#: dashboards/admin/users/views.py:70
+msgid "Unable to update user."
+msgstr "Não conseguir atualizar usuário."
+
+#: dashboards/admin/users/views.py:104
+msgid "Unable to retrieve user roles."
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_create.html:17
+msgid "From here you can create a new user and assign them to a project."
+msgstr ""
+"A partir daí você pode criar um novo usuário e atribuir-lhes um projeto."
+
+#: dashboards/admin/users/templates/users/_update.html:7
+#: dashboards/admin/users/templates/users/_update.html:22
+#: dashboards/admin/users/templates/users/update.html:7
+msgid "Update User"
+msgstr "Atualizar Usuário"
+
+#: dashboards/admin/users/templates/users/_update.html:17
+msgid ""
+"From here you can edit the user's details, including their default project."
+msgstr ""
+"A partir daí você pode editar os detalhes do usuário, incluindo o projeto "
+"padrão."
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:3
+#: dashboards/project/volumes/templates/volumes/detail.html:3
+msgid "Volume Details"
+msgstr "Detalhes Volume"
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:6
+#: dashboards/project/volumes/templates/volumes/detail.html:6
+msgid "Volume Detail"
+msgstr "Detalhe Volume"
+
+#: dashboards/project/dashboard.py:24
+msgid "Manage Compute"
+msgstr "Gerenciar Instâncias"
+
+#: dashboards/project/dashboard.py:35
+msgid "Object Store"
+msgstr "Armazenamento de Objecto"
+
+#: dashboards/project/access_and_security/panel.py:26
+#: dashboards/project/instances/workflows.py:348
+msgid "Access & Security"
+msgstr "Acesso e Segurança"
+
+#: dashboards/project/access_and_security/views.py:51
+msgid "Unable to retrieve keypair list."
+msgstr "Não foi possível recuperar a lista de par de chaves."
+
+#: dashboards/project/access_and_security/views.py:60
+#: dashboards/project/access_and_security/security_groups/views.py:74
+msgid "Unable to retrieve security groups."
+msgstr "Não é possível recuperar grupos de segurança"
+
+#: dashboards/project/access_and_security/views.py:69
+#: dashboards/project/access_and_security/floating_ips/workflows.py:49
+msgid "Unable to retrieve floating IP addresses."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:32
+msgid "Pool"
+msgstr "Fornecimento"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:43
+#, python-format
+msgid "Allocated Floating IP %(ip)s."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:47
+msgid "Unable to allocate Floating IP."
+msgstr "Não é possível atribuido IP"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:37
+msgid "Allocate IP To Project"
+msgstr "Alocar IP para projeto"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:47
+msgid "Release"
+msgstr "Solte"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:48
+msgid "Released"
+msgstr "Soltava"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:49
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:22
+msgid "Floating IP"
+msgstr "IP Flutuante"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:6
+#: dashboards/project/instances/tables.py:219
+msgid "Associate Floating IP"
+msgstr "Associado IP Flutuante"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:76
+msgid "Disassociate Floating IP"
+msgstr "Dissociado IP Flutuante"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:90
+#, python-format
+msgid "Successfully disassociated Floating IP: %s"
+msgstr "Sucesso dissociado IP Flutuante: %s"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:94
+msgid "Unable to disassociate floating IP."
+msgstr "Impossível dissociar IP flutuante."
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:114
+#: dashboards/project/access_and_security/floating_ips/workflows.py:36
+#: dashboards/project/instances/tables.py:69
+#: dashboards/project/instances/tables.py:89
+#: dashboards/project/instances/tables.py:106
+#: dashboards/project/instances/tables.py:135
+#: dashboards/project/volumes/tables.py:206
+msgid "Instance"
+msgstr "Instância"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:117
+msgid "Floating IP Pool"
+msgstr "Fornecimento de IP Flutuante"
+
+#: dashboards/project/access_and_security/floating_ips/views.py:65
+msgid "Unable to retrieve floating IP pools."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:68
+msgid "No floating IP pools available."
+msgstr "Sem fornecimento de IP flutuantes disponível."
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:40
+msgid "Select the IP address you wish to associate with the selected instance."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:53
+msgid "Select an IP address"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:55
+msgid "No IP addresses available"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:76
+#: dashboards/project/volumes/forms.py:160
+msgid "Select an instance"
+msgstr "Selecione uma instância"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:78
+#: dashboards/project/volumes/forms.py:162
+msgid "No instances available"
+msgstr "Não há instâncias disponíveis"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:97
+msgid "Manage Floating IP Associations"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:98
+msgid "Associate"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:99
+#, python-format
+msgid "IP address %s associated."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:100
+#, python-format
+msgid "Unable to associate IP address %s."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:38
+#: dashboards/project/access_and_security/keypairs/forms.py:49
+#: dashboards/project/access_and_security/keypairs/tables.py:52
+msgid "Keypair Name"
+msgstr "Par de chaves nome"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:40
+msgid ""
+"Keypair names may only contain letters, numbers, underscores and hyphens."
+msgstr ""
+"Nomes par de chaves pode conter apenas letras, números, sublinhados e hífens."
+
+#: dashboards/project/access_and_security/keypairs/forms.py:51
+msgid "Public Key"
+msgstr "Chave Pública"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:60
+#, python-format
+msgid "Successfully imported public key: %s"
+msgstr "Importado com êxito chave pública: %s"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:65
+msgid "Unable to import keypair."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:30
+#: dashboards/project/instances/tables.py:295
+#: dashboards/project/instances/workflows.py:335
+msgid "Keypair"
+msgstr "Par de chaves"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:31
+#: dashboards/project/access_and_security/keypairs/tables.py:60
+msgid "Keypairs"
+msgstr "Par de Chaves"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:39
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html:6
+msgid "Import Keypair"
+msgstr "Importar Par de Chaves"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:46
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html:6
+msgid "Create Keypair"
+msgstr "Criar Par de Chaves"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:53
+msgid "Fingerprint"
+msgstr "Impressão Digital"
+
+#: dashboards/project/access_and_security/keypairs/views.py:74
+#, python-format
+msgid "Unable to create keypair: %(exc)s"
+msgstr "Não é possível criar par de chaves: %(exc)s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:46
+#, python-format
+msgid "Successfully created security group: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:52
+msgid "Unable to create security group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:57
+#: dashboards/project/access_and_security/security_groups/tables.py:93
+msgid "IP Protocol"
+msgstr "Protocolo IP"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:61
+msgid "The protocol which this rule should be applied to."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:65
+#: dashboards/project/access_and_security/security_groups/forms.py:71
+#: dashboards/project/access_and_security/security_groups/tables.py:95
+msgid "From Port"
+msgstr "De Porto"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:66
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP type in the range (-1: 255)"
+msgstr ""
+"TCP/UDP: Insira o valor inteiro entre 1 e 65535. ICMP: Digite um valor para "
+"tipo de ICMP na gama (-1: 255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:72
+#: dashboards/project/images_and_snapshots/images/tables.py:115
+msgid "Type"
+msgstr "Tipo"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:74
+#: dashboards/project/access_and_security/security_groups/forms.py:80
+#: dashboards/project/access_and_security/security_groups/tables.py:96
+msgid "To Port"
+msgstr "à Porta"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:75
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP code in the range (-1: 255)"
+msgstr ""
+"TCP/UDP: Insira o valor inteiro entre 1 e 65535. ICMP: Digite um valor para "
+"código de ICMP na gama (-1: 255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:81
+msgid "Code"
+msgstr "Código"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:84
+msgid "Source Group"
+msgstr "Grupo Origem"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:86
+msgid ""
+"To specify an allowed IP range, select CIDR. To allow access from all "
+"members of another security group select Source Group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:94
+msgid "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:121
+msgid "The ICMP type is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:124
+msgid "The ICMP code is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:127
+msgid "The ICMP type not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:130
+msgid "The ICMP code not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:134
+msgid "The \"from\" port number is invalid."
+msgstr "O \"de\" porto é inválido."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:137
+msgid "The \"to\" port number is invalid."
+msgstr "O \"à\" porto é inválido."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:140
+msgid ""
+"The \"to\" port number must be greater than or equal to the \"from\" port "
+"number."
+msgstr ""
+"O número da porta \"para\" deve ser maior ou igual ao número de porta \"de\""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:146
+msgid "Either CIDR or Source Group may be specified, but not both."
+msgstr "Ou CIDR ou Grupo Origem pode ser especificado, mas não ambos."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:168
+#, python-format
+msgid "Successfully added rule: %s"
+msgstr "Regra adicionada com sucesso: %s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:173
+msgid "Unable to add rule to security group."
+msgstr "Não é possível adicionar regra para grupo de segurança"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:31
+msgid "Security Group"
+msgstr "Grupo de Segurança"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:32
+#: dashboards/project/access_and_security/security_groups/tables.py:66
+#: dashboards/project/instances/workflows.py:340
+#: dashboards/project/instances/templates/instances/_detail_overview.html:49
+msgid "Security Groups"
+msgstr "Grupos de Seguranças"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:45
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html:6
+msgid "Create Security Group"
+msgstr "Criar a Grupo de Segurança"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:52
+msgid "Edit Rules"
+msgstr "Editar Regras"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:72
+msgid "Rule"
+msgstr "Regra"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:73
+msgid "Rules"
+msgstr "Regras"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:97
+msgid "Source"
+msgstr "Origem"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:107
+msgid "Security Group Rules"
+msgstr "Regras para Grupos de Seguranças"
+
+#: dashboards/project/access_and_security/security_groups/views.py:60
+msgid "Unable to retrieve security group."
+msgstr "Não é possível recuperar grupo de segurança"
+
+#: dashboards/project/access_and_security/security_groups/views.py:80
+#, python-format
+msgid "%s (current)"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/index.html:6
+msgid "Access &amp; Security"
+msgstr "Acesso e Segurança"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:8
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html:3
+msgid "Allocate Floating IP"
+msgstr "Alocar IP Flutuante"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:18
+msgid "Allocate a floating IP from a given floating ip pool."
+msgstr ""
+"Atribuir um IP flutuante a partir de um determinado ip fornecimento "
+"flutuante."
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:20
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:19
+msgid "Project Quotas"
+msgstr "Cotas de Projeto"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:31
+msgid "Allocate IP"
+msgstr "Atribuir IP"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:17
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:17
+msgid ""
+"Keypairs are ssh credentials which are injected into images when they are "
+"launched. Creating a new key pair registers the public key and downloads the "
+"private key (a .pem file)."
+msgstr ""
+"Pares de chaves são credenciais ssh que são injetados em imagens quando eles "
+"são lançados. Criando um novo par de chaves registra a chave pública e "
+"transfere a chave privada (um arquivo .pem)."
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:18
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:18
+msgid "Protect and use the key as you would any normal ssh private key."
+msgstr ""
+"Proteger e utilizar a chave como faria com qualquer chave ssh privado normal."
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:6
+msgid "Download Keypair"
+msgstr "Puxar a Par de Chaves"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:11
+#, python-format
+msgid ""
+"The keypair &quot;%(keypair_name)s&quot; should download automatically. If "
+"not use the link below."
+msgstr ""
+"O par de chaves &quot;%(keypair_name)s&quot; deve fazer o download "
+"automaticamente. Se não usar o link abaixo."
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:15
+#, python-format
+msgid "Download keypair &quot;%(keypair_name)s&quot;"
+msgstr "Baixe par chave &quot;%(keypair_name)s&quot;"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:18
+msgid "From here you can create a new security group"
+msgstr "A partir daí você pode criar um novo grupo de segurança"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:9
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html:6
+msgid "Edit Security Group Rules"
+msgstr "Editar Grupo de Segurança Regras"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:12
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:19
+msgid "Add Rule"
+msgstr "Adicionar regra"
+
+#: dashboards/project/containers/browsers.py:26
+msgid "Swift"
+msgstr ""
+
+#: dashboards/project/containers/browsers.py:29
+#: dashboards/project/containers/tables.py:40
+msgid "Container"
+msgstr "Recipiente"
+
+#: dashboards/project/containers/forms.py:39
+msgid "Slash is not an allowed character."
+msgstr "Barra não é um caractere permitido."
+
+#: dashboards/project/containers/forms.py:49
+#: dashboards/project/containers/tables.py:121
+msgid "Container Name"
+msgstr "Nome de recipiente"
+
+#: dashboards/project/containers/forms.py:57
+msgid "Container created successfully."
+msgstr "Recipiente criado com sucesso"
+
+#: dashboards/project/containers/forms.py:68
+msgid "Folder created successfully."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:71
+msgid "Unable to create container."
+msgstr "Não é possível criar recipiente"
+
+#: dashboards/project/containers/forms.py:79
+#: dashboards/project/containers/tables.py:253
+msgid "Object Name"
+msgstr "Nome de Objeto"
+
+#: dashboards/project/containers/forms.py:81
+msgid "File"
+msgstr "Arquivo"
+
+#: dashboards/project/containers/forms.py:95
+msgid "Object was successfully uploaded."
+msgstr "Objeto foi carregado com sucesso"
+
+#: dashboards/project/containers/forms.py:98
+msgid "Unable to upload object."
+msgstr "Não é possível carregar objeto"
+
+#: dashboards/project/containers/forms.py:102
+msgid "Destination container"
+msgstr "Nome do recipiente destino"
+
+#: dashboards/project/containers/forms.py:106
+msgid "Destination object name"
+msgstr "Nome do objeto destino"
+
+#: dashboards/project/containers/forms.py:137
+#: dashboards/project/containers/forms.py:163
+msgid "Unable to copy object."
+msgstr "Não é possível copiar objetos"
+
+#: dashboards/project/containers/forms.py:153
+#, python-format
+msgid "Copied \"%(orig)s\" to \"%(dest)s\" as \"%(new)s\"."
+msgstr ""
+
+#: dashboards/project/containers/panel.py:29
+#: dashboards/project/containers/tables.py:41
+#: dashboards/project/containers/tables.py:128
+#: dashboards/project/containers/templates/containers/index.html:7
+msgid "Containers"
+msgstr "Recipientes"
+
+#: dashboards/project/containers/tables.py:62
+#: dashboards/project/containers/templates/containers/_create.html:7
+#: dashboards/project/containers/templates/containers/_create.html:22
+#: dashboards/project/containers/templates/containers/create.html:6
+msgid "Create Container"
+msgstr "Criar Recipiente"
+
+#: dashboards/project/containers/tables.py:69
+msgid "View Container"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:81
+#: dashboards/project/containers/templates/containers/_upload.html:23
+#: dashboards/project/containers/templates/containers/upload.html:3
+msgid "Upload Object"
+msgstr "Mandar Objeto"
+
+#: dashboards/project/containers/tables.py:137
+#: dashboards/project/containers/tables.py:156
+msgid "Object"
+msgstr "Objeto"
+
+#: dashboards/project/containers/tables.py:138
+#: dashboards/project/containers/tables.py:157
+#: dashboards/project/containers/tables.py:263
+msgid "Objects"
+msgstr "Objetos"
+
+#: dashboards/project/containers/tables.py:149
+msgid "Folder"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:150
+msgid "Folders"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:163
+msgid "Copy"
+msgstr "Copia"
+
+#: dashboards/project/containers/tables.py:176
+msgid "Download"
+msgstr "Puxar"
+
+#: dashboards/project/containers/tables.py:232
+msgid "Create Folder"
+msgstr ""
+
+#: dashboards/project/containers/views.py:53
+msgid "Unable to retrieve container list."
+msgstr "Não é possível recuperar lista de recipientes"
+
+#: dashboards/project/containers/views.py:82
+msgid "Unable to retrieve object list."
+msgstr "Não é possível recuperar lista de objetos"
+
+#: dashboards/project/containers/views.py:166
+msgid "Unable to retrieve object."
+msgstr "Não é possível recuperar objeto"
+
+#: dashboards/project/containers/views.py:200
+msgid "Unable to list containers."
+msgstr "Não é possível recuperar alista recipientes"
+
+#: dashboards/project/containers/templates/containers/_copy.html:7
+#: dashboards/project/containers/templates/containers/_copy.html:22
+#: dashboards/project/containers/templates/containers/copy.html:3
+#: dashboards/project/containers/templates/containers/copy.html:6
+msgid "Copy Object"
+msgstr "Copiar Objeto"
+
+#: dashboards/project/containers/templates/containers/_copy.html:17
+msgid ""
+"Make a new copy of an existing object to store in this or another container. "
+"You may also specify a path at which the new copy should live inside of the "
+"selected container."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_create.html:17
+msgid ""
+"A container is a storage compartment for your data and provides a way for "
+"you to organize your data. You can think of a container as a folder in "
+"Windows &reg; or a directory in UNIX &reg;. The primary difference between a "
+"container and these other file system concepts is that containers cannot be "
+"nested. You can, however, create an unlimited number of containers within "
+"your account. Data must be stored in a container so you must have at least "
+"one container defined in your account prior to uploading data."
+msgstr ""
+"Um container é um compartimento de armazenamento para seus dados e fornece "
+"uma maneira para você organizar seus dados. Você pode pensar em um "
+"recipiente, como uma pasta no Windows &reg; ou um diretório no UNIX &reg;. A "
+"principal diferença entre um recipiente e estes conceitos no sistema de "
+"arquivos é que os recipientes não podem ser aninhados. Você pode, no "
+"entanto, criar um número ilimitado de recipientes dentro de sua conta. Os "
+"dados devem ser armazenados em um recipiente de modo que você deve ter pelo "
+"menos um recipiente definido em sua conta antes de carregar os dados."
+
+#: dashboards/project/containers/templates/containers/_upload.html:8
+msgid "Upload Object To Container"
+msgstr "Carregar objeto para o recipiente"
+
+#: dashboards/project/containers/templates/containers/_upload.html:18
+msgid ""
+"An object is the basic storage entity and any optional metadata that "
+"represents the files you store in the OpenStack Object Storage system. When "
+"you upload data to OpenStack Object Storage, the data is stored as-is (no "
+"compression or encryption) and consists of a location (container), the "
+"object's name, and any metadata consisting of key/value pairs."
+msgstr ""
+"Um objeto é a entidade básica de armazenamento e quaisquer metadados "
+"opcional que representa os arquivos que você armazena no sistema de "
+"armazenamento OpenStack objeto. Quando você carrega de dados para "
+"armazenamento OpenStack objeto os dados são armazenados como está (sem "
+"compressão ou criptografia) e consiste de um local (recipiente), o nome do "
+"objeto, e quaisquer metadados que consiste de pares chave / valor."
+
+#: dashboards/project/containers/templates/containers/upload.html:6
+msgid "Upload Objects"
+msgstr "Carregar Objetos"
+
+#: dashboards/project/images_and_snapshots/panel.py:26
+msgid "Images & Snapshots"
+msgstr "Imagens e Instantâneos"
+
+#: dashboards/project/images_and_snapshots/views.py:63
+msgid "Unable to retrieve images."
+msgstr "Não é possível recuperar imagens."
+
+#: dashboards/project/images_and_snapshots/views.py:74
+msgid "Unable to retrieve snapshots."
+msgstr "Não é possível recuperar instantâneos."
+
+#: dashboards/project/images_and_snapshots/views.py:82
+#: dashboards/project/volumes/forms.py:65
+msgid "Unable to retrieve volume snapshots."
+msgstr "Não é possível recuperar volume de instantâneos."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:42
+msgid "Image Location"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:43
+msgid "An external (HTTP) URL to load the image from."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:46
+#: dashboards/project/images_and_snapshots/images/forms.py:130
+#: dashboards/project/images_and_snapshots/images/tables.py:126
+msgid "Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:50
+msgid "AKI - Amazon Kernel Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:53
+msgid "AMI - Amazon Machine Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:56
+msgid "ARI - Amazon Ramdisk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:59
+msgid "ISO - Optical Disk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:61
+msgid "QCOW2 - QEMU Emulator"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:68
+msgid "Minimum Disk (GB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:69
+#: dashboards/project/images_and_snapshots/images/forms.py:76
+msgid ""
+"The minimum disk size required to boot the image. If unspecified, this value "
+"defaults to 0 (no minimum)."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:75
+msgid "Minimum Ram (MB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:82
+#: dashboards/project/images_and_snapshots/images/forms.py:134
+#: dashboards/project/images_and_snapshots/images/tables.py:123
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:15
+msgid "Public"
+msgstr "Público"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:106
+#, python-format
+msgid "Your image %s has been queued for creation."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:110
+msgid "Unable to create new image."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:116
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:48
+msgid "Kernel ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:121
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:52
+msgid "Ramdisk ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:126
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:44
+msgid "Architecture"
+msgstr "Arquitetura"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:138
+#, python-format
+msgid "Unable to update image \"%s\"."
+msgstr "Não é possível atualizar imagem\"%s\"."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:162
+msgid "Image was successfully updated."
+msgstr "Imagem foi atualizado com sucesso."
+
+#: dashboards/project/images_and_snapshots/images/tables.py:34
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:33
+#: dashboards/project/instances/workflows.py:455
+msgid "Launch"
+msgstr "Lançar"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:46
+#: dashboards/project/images_and_snapshots/images/tables.py:82
+#: dashboards/project/instances/workflows.py:168
+#: dashboards/project/instances/workflows.py:173
+msgid "Image"
+msgstr "Imagen"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:61
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:31
+msgid "Create Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tabs.py:38
+msgid "Unable to retrieve image details."
+msgstr "Não é possível recuperar detalhes da imagem"
+
+#: dashboards/project/images_and_snapshots/images/views.py:61
+msgid "Unable to retrieve image."
+msgstr "Não é possível recuperar imagen."
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:37
+msgid "Instance ID"
+msgstr "ID do Instâncias"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:40
+#: dashboards/project/volumes/forms.py:193
+msgid "Snapshot Name"
+msgstr "Nome de Instantâneo"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:50
+#, python-format
+msgid "Snapshot \"%(name)s\" created for instance \"%(inst)s\""
+msgstr "Instantâneo \"%(name)s\" criado por instâncias \"%(inst)s\""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:56
+msgid "Unable to create snapshot."
+msgstr "Não é possível criar instantâneo."
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:48
+#: dashboards/project/instances/workflows.py:107
+#: dashboards/project/instances/workflows.py:169
+msgid "Snapshot"
+msgstr "Instantâneo"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:49
+msgid "Snapshots"
+msgstr "Instantâneos"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:55
+msgid "Instance Snapshots"
+msgstr "Instantâneos Instância"
+
+#: dashboards/project/images_and_snapshots/snapshots/views.py:53
+msgid "Unable to retrieve instance."
+msgstr "Não é possível recuperar instantâneo."
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:6
+msgid "Images &amp; Snapshots"
+msgstr "Imagens e Instantâneo"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:6
+msgid "Create An Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:18
+msgid "Specify an image to upload to the Image Service."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:21
+msgid ""
+"Currently only images available via an HTTP URL are supported. The image "
+"location must be accessible to the Image Service. Compressed image binaries "
+"are supported (.zip and .tar.gz.)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:24
+msgid "Please note: "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:25
+msgid ""
+"The Image Location field MUST be a valid and direct URL to the image binary. "
+"URLs that redirect or serve error pages will result in unusable images."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:3
+msgid "Image Overview"
+msgstr "Resumo da Imagem"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:6
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:7
+#: dashboards/project/instances/templates/instances/_detail_overview.html:6
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:6
+msgid "Info"
+msgstr "Informações"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:17
+msgid "Checksum"
+msgstr "Checksum"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:19
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:39
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:28
+msgid "Created"
+msgstr "Criado"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:21
+msgid "Updated"
+msgstr "Atualizado"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:27
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:34
+#: dashboards/project/instances/templates/instances/_detail_overview.html:19
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:23
+msgid "Specs"
+msgstr "Especificações"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:32
+msgid "Container Format"
+msgstr "Formato de Recpientes"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:34
+msgid "Disk Format"
+msgstr "Formato de Disco"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:40
+msgid "Custom Properties"
+msgstr "Propriedades Personalizadas"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:56
+msgid "Euca2ools state"
+msgstr "Estado de Euca2ools"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:64
+msgid "Image Type"
+msgstr "Tipo de Imagem"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html:4
+msgid "Image Detail "
+msgstr "Detalhe da Imagem"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:8
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:3
+#: dashboards/project/instances/tables.py:179
+#: dashboards/project/volumes/tables.py:76
+msgid "Create Snapshot"
+msgstr "Criar Instantâneo"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:18
+msgid "Snapshots preserve the disk state of a running instance."
+msgstr "Instantâneos preservar o estado do disco de uma instância em execução."
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:20
+#: dashboards/project/instances/workflows.py:75
+#: dashboards/project/instances/workflows.py:110
+#: dashboards/project/instances/templates/instances/_detail_overview.html:93
+#: dashboards/project/volumes/tables.py:37
+#: dashboards/project/volumes/tables.py:182
+msgid "Volume"
+msgstr "Volume"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:38
+#: dashboards/project/instances/templates/instances/_detail_overview.html:29
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:27
+msgid "GB"
+msgstr "GB"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:6
+msgid "Create a Snapshot"
+msgstr "Criar um Instantâneo"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:3
+#, fuzzy
+msgid "Volume Snapshot Details"
+msgstr "Instantâneos Volume"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:6
+#, fuzzy
+msgid "Volume Snapshot Detail"
+msgstr "Instantâneo Volume"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:34
+#: dashboards/project/instances/workflows.py:76
+msgid "Volume Snapshot"
+msgstr "Instantâneo Volume"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:35
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:85
+msgid "Volume Snapshots"
+msgstr "Instantâneos Volume"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:43
+#: dashboards/project/volumes/tables.py:59
+#: dashboards/project/volumes/templates/volumes/_create.html:8
+#: dashboards/project/volumes/templates/volumes/_create.html:55
+msgid "Create Volume"
+msgstr "Criar a Volume"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:80
+#: dashboards/project/volumes/forms.py:26
+msgid "Volume Name"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:41
+#, fuzzy
+msgid "Unable to retrieve snapshot details."
+msgstr "Não é possível recuperar instantâneos."
+
+#: dashboards/project/instances/forms.py:45
+#, python-format
+msgid "Instance \"%s\" updated."
+msgstr "Instância \"%s\" atualizado."
+
+#: dashboards/project/instances/forms.py:50
+msgid "Unable to update instance."
+msgstr "Não é possível atualizar instância."
+
+#: dashboards/project/instances/tables.py:67
+msgid "Terminate"
+msgstr "Terminar"
+
+#: dashboards/project/instances/tables.py:68
+msgid "Scheduled termination of"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:87
+msgid "Reboot"
+msgstr "Reiniciar"
+
+#: dashboards/project/instances/tables.py:88
+msgid "Rebooted"
+msgstr "Reiniciado"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Pause"
+msgstr "Pausar"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Unpause"
+msgstr "Retomar"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Paused"
+msgstr "Pausado"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Unpaused"
+msgstr "Retomado"
+
+#: dashboards/project/instances/tables.py:133
+msgid "Suspend"
+msgstr "Suspender"
+
+#: dashboards/project/instances/tables.py:133
+msgid "Resume"
+msgstr "Retomar"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Suspended"
+msgstr "Suspenso"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Resumed"
+msgstr "Retomado"
+
+#: dashboards/project/instances/tables.py:162
+#: dashboards/project/instances/workflows.py:454
+#: dashboards/project/instances/templates/instances/launch.html:3
+#: dashboards/project/instances/templates/instances/launch.html:6
+msgid "Launch Instance"
+msgstr "Lançamento Instância"
+
+#: dashboards/project/instances/tables.py:169
+#: dashboards/project/instances/templates/instances/_update.html:7
+msgid "Edit Instance"
+msgstr "Editar Instância"
+
+#: dashboards/project/instances/tables.py:189
+msgid "VNC Console"
+msgstr "VNC Console"
+
+#: dashboards/project/instances/tables.py:204
+msgid "View Log"
+msgstr "Ver a Sessão"
+
+#: dashboards/project/instances/tables.py:252
+#, python-format
+msgid "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disk"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:259
+#: dashboards/project/instances/tables.py:266
+msgid "Not available"
+msgstr "Não está disponível"
+
+#: dashboards/project/instances/tabs.py:36
+msgid "Log"
+msgstr "Sessão"
+
+#: dashboards/project/instances/tabs.py:48
+#: dashboards/project/instances/views.py:106
+#, python-format
+msgid "Unable to get log for instance \"%s\"."
+msgstr "Não é possível obter sessão para instância \"%s\"."
+
+#: dashboards/project/instances/tabs.py:55
+msgid "VNC"
+msgstr "VNC"
+
+#: dashboards/project/instances/tabs.py:70
+#: dashboards/project/instances/views.py:122
+#, python-format
+msgid "Unable to get VNC console for instance \"%s\"."
+msgstr "Não foi possível obter VNC consola, para instância \"%s\"."
+
+#: dashboards/project/instances/views.py:59
+msgid "Unable to retrieve instances."
+msgstr "Não é possível recuperar instâncias."
+
+#: dashboards/project/instances/views.py:144
+msgid "Unable to retrieve instance details."
+msgstr "Não é possível recuperar dados de instância."
+
+#: dashboards/project/instances/views.py:179
+#, python-format
+msgid "Unable to retrieve details for instance \"%s\"."
+msgstr "Não é possível recuperar dados para instância \"%s\"."
+
+#: dashboards/project/instances/workflows.py:53
+msgid "Project & User"
+msgstr "Projeto e Usuário"
+
+#: dashboards/project/instances/workflows.py:66
+msgid "Don't boot from a volume."
+msgstr "Não inicializar a partir de um volume."
+
+#: dashboards/project/instances/workflows.py:67
+msgid "Boot from volume."
+msgstr "Inicializar a partir de um volume"
+
+#: dashboards/project/instances/workflows.py:68
+msgid "Boot from volume snapshot (creates a new volume)."
+msgstr "Inicializar a partir de instantâneo de volume (cria um novo volume)."
+
+#: dashboards/project/instances/workflows.py:72
+#: dashboards/project/instances/workflows.py:90
+msgid "Volume Options"
+msgstr "Opções de Volume"
+
+#: dashboards/project/instances/workflows.py:78
+#: dashboards/project/volumes/forms.py:126
+msgid "Device Name"
+msgstr "Nome do Dispositivo"
+
+#: dashboards/project/instances/workflows.py:81
+msgid "Volume mount point (e.g. 'vda' mounts at '/dev/vda')."
+msgstr "Volume ponto de montagem (suportes 'VDA' por exemplo, em '/dev/vda' )."
+
+#: dashboards/project/instances/workflows.py:83
+msgid "Delete on Terminate"
+msgstr "Excluir da cessação"
+
+#: dashboards/project/instances/workflows.py:86
+msgid "Delete volume on instance terminate"
+msgstr "Apagar volume de rescisão instância"
+
+#: dashboards/project/instances/workflows.py:100
+#, python-format
+msgid "Please choose a volume, or select %s."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:117
+msgid "Select Volume"
+msgstr "Selecione Volume"
+
+#: dashboards/project/instances/workflows.py:125
+msgid "Unable to retrieve list of volumes."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:129
+msgid "Select Volume Snapshot"
+msgstr "Selecione Volume Instantâneo"
+
+#: dashboards/project/instances/workflows.py:138
+msgid "Unable to retrieve list of volume snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:171
+msgid "Instance Source"
+msgstr "Origem Instância"
+
+#: dashboards/project/instances/workflows.py:174
+msgid "Instance Snapshot"
+msgstr "Instantâneo Instância"
+
+#: dashboards/project/instances/workflows.py:178
+msgid "Size of image to launch."
+msgstr "Tamanho da imagem para o lançamento."
+
+#: dashboards/project/instances/workflows.py:179
+msgid "Instance Count"
+msgstr "Contagem Instância"
+
+#: dashboards/project/instances/workflows.py:182
+msgid "Number of instances to launch."
+msgstr "Número de casos de lançar."
+
+#: dashboards/project/instances/workflows.py:185
+msgid "Details"
+msgstr "Detalhes"
+
+#: dashboards/project/instances/workflows.py:198
+msgid ""
+"There are no image sources available; you must first create an image before "
+"attempting to launch an instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:203
+msgid "Please select an option for the instance source."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:212
+msgid ""
+"Launching multiple instances is only supported for images and instance "
+"snapshots."
+msgstr ""
+"Lançamento várias instâncias é suportado apenas por imagens e instantâneos "
+"de instância."
+
+#: dashboards/project/instances/workflows.py:229
+msgid "Unable to retrieve public images."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:244
+msgid "Unable to retrieve images for the current project."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:267
+msgid "Select Image"
+msgstr "Selecione a imagem"
+
+#: dashboards/project/instances/workflows.py:269
+msgid "No images available."
+msgstr "Não há imagens disponíveis."
+
+#: dashboards/project/instances/workflows.py:278
+msgid "Select Instance Snapshot"
+msgstr "Selecione Instantâneo Instância"
+
+#: dashboards/project/instances/workflows.py:280
+msgid "No snapshots available."
+msgstr "Não há instantâneos disponíveis."
+
+#: dashboards/project/instances/workflows.py:291
+msgid "Unable to retrieve instance flavors."
+msgstr "Não é possível recuperar os sabores de instância."
+
+#: dashboards/project/instances/workflows.py:304 usage/base.py:114
+msgid "Unable to retrieve quota information."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:337
+msgid "Which keypair to use for authentication."
+msgstr "Que par de chaves para autenticação."
+
+#: dashboards/project/instances/workflows.py:344
+msgid "Launch instance in these security groups."
+msgstr "Lançamento instância, esses grupos de segurança."
+
+#: dashboards/project/instances/workflows.py:349
+msgid ""
+"Control access to your instance via keypairs, security groups, and other "
+"mechanisms."
+msgstr ""
+"Controlar o acesso a sua instância via pares de chaves, grupos de segurança "
+"e outros mecanismos"
+
+#: dashboards/project/instances/workflows.py:359
+msgid "Unable to retrieve keypairs."
+msgstr "Não é possível recuperar pares de chaves."
+
+#: dashboards/project/instances/workflows.py:361
+msgid "Select a keypair"
+msgstr "Selecione um par de chaves"
+
+#: dashboards/project/instances/workflows.py:363
+msgid "No keypairs available."
+msgstr "Não pares de chaves disponíveis."
+
+#: dashboards/project/instances/workflows.py:372
+msgid "Unable to retrieve list of security groups"
+msgstr "Não foi possível recuperar a lista de grupos de segurança"
+
+#: dashboards/project/instances/workflows.py:392
+msgid "Customization Script"
+msgstr "Programa Personalização"
+
+#: dashboards/project/instances/workflows.py:394
+msgid ""
+"A script or set of commands to be executed after the instance has been built "
+"(max 16kb)."
+msgstr ""
+"Um programa ou conjunto de comandos para ser executado depois que a "
+"instância foi construída (max 16kb)."
+
+#: dashboards/project/instances/workflows.py:401
+msgid "Post-Creation"
+msgstr "Pós-Criação"
+
+#: dashboards/project/instances/workflows.py:415
+msgid "Launch instance withthese networks"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:419
+msgid "Networking"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:421
+msgid "Select networks for your instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:433
+msgid "Unable to retrieve networks."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:456
+#, python-format
+msgid "Launched %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:457
+#, python-format
+msgid "Unable to launch %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:470
+#, python-format
+msgid "%s instances"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:473
+msgid "instance"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:4
+msgid "Instance Console Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:7
+msgid "Log Length"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:9
+msgid "Go"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:11
+msgid "View Full Log"
+msgstr "Ver Registo Completo"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:3
+msgid "Instance Overview"
+msgstr "Resumo de Instâncias"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:27
+msgid "VCPU"
+msgstr "VCPU"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:28
+#: usage/tables.py:20
+msgid "Disk"
+msgstr "Disco"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:34
+msgid "IP Addresses"
+msgstr "Endereços IP"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:59
+msgid "No rules defined."
+msgstr "Sem regras definidas."
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:68
+msgid "Meta"
+msgstr "Meta"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:71
+msgid "Key Name"
+msgstr "Nome da Chave"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:84
+msgid "Volumes Attached"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:88
+#: dashboards/project/volumes/tables.py:167
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:38
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:45
+msgid "Attached To"
+msgstr "Anexado para"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:90
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:42
+msgid "on"
+msgstr "posto"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:94
+msgid "No volumes attached."
+msgstr "Sem volumes ligados."
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:3
+msgid "Instance VNC Console"
+msgstr "Consola de VNC Instância"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid ""
+"If VNC console is not responding to keyboard input: click the grey status "
+"bar below."
+msgstr ""
+"Se VNC console não está respondendo a entrada do teclado: clique na barra de "
+"status cinza abaixo."
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid "Click here to show only VNC"
+msgstr "Clique aqui para mostrar apenas VNC"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:8
+msgid "VNC console is currently unavailabe. Please try again later."
+msgstr ""
+"VNC consola está disponível no momento. Por favor, tente novamente mais "
+"tarde."
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:9
+msgid "Reload"
+msgstr "Recarregar"
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:2
+msgid ""
+"You can customize your instance after it's launched using the options "
+"available here."
+msgstr ""
+"Você pode personalizar o seu instância após que é lançado utilizando as "
+"opções disponíveis aqui."
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:3
+msgid ""
+"The \"Customization Script\" field is analogous to \"User Data\" in other "
+"systems."
+msgstr ""
+"O \"Script Personalização \" área é análogo ao de \"Dados Usuário \" em "
+"outros sistemas."
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:3
+msgid "Specify the details for launching an instance."
+msgstr "Especifique os detalhes para o lançamento de uma instância."
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:4
+msgid ""
+"The chart below shows the resources used by this project in relation to the "
+"project's quotas."
+msgstr ""
+"O gráfico abaixo mostra os recursos utilizados por este projeto em relação "
+"às cotas do projeto."
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:6
+msgid "Flavor Details"
+msgstr "Detalhes Sabor"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+msgid "Total Disk"
+msgstr "Disco Total"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "MB"
+msgstr "MB"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:21
+msgid "Number of Instances"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:29
+msgid "Number of VCPUs"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+#, fuzzy
+msgid "Total RAM"
+msgstr "Disco Total"
+
+#: dashboards/project/instances/templates/instances/_launch_volumes_help.html:3
+msgid ""
+"An instance can be launched with varying types of attached storage. You may "
+"select from those options here."
+msgstr ""
+"Um instância pode ser lançado com diferentes tipos de armazenamento anexado. "
+"Você pode selecionar entre as opções aqui."
+
+#: dashboards/project/instances/templates/instances/_update.html:17
+msgid "You may update the editable properties of your instance here."
+msgstr "Você pode atualizar as propriedades editáveis de sua instância aqui."
+
+#: dashboards/project/instances/templates/instances/detail.html:3
+msgid "Instance Detail"
+msgstr "Detalhe Instância"
+
+#: dashboards/project/instances/templates/instances/update.html:3
+#: dashboards/project/instances/templates/instances/update.html:6
+msgid "Update Instance"
+msgstr "Atualizar Instância"
+
+#: dashboards/project/networks/tables.py:81
+msgid "Add Subnet"
+msgstr ""
+
+#: dashboards/project/networks/views.py:86
+msgid "Unable to retrieve network details."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:37
+msgid "Network Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:42
+msgid ""
+"From here you can create a new network.\n"
+"In addition a subnet associated with the network can be created in the next "
+"panel."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:56
+msgid "Subnet Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:61
+#: dashboards/project/networks/subnets/forms.py:48
+msgid "Network address in CIDR format (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:67
+msgid "Gateway IP (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:70
+#: dashboards/project/networks/subnets/forms.py:57
+#: dashboards/project/networks/subnets/forms.py:107
+msgid "IP address of Gateway (e.g. 192.168.0.1)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:77
+msgid ""
+"You can create a subnet associated with the new network, in which case "
+"\"Network Address\" must be specified. If you wish to create a network "
+"WITHOUT a subnet, uncheck the \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:89
+msgid "Specify \"Network Address\" or clear \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:94
+#: dashboards/project/networks/subnets/forms.py:70
+msgid "Network Address and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:98
+#: dashboards/project/networks/subnets/forms.py:74
+#: dashboards/project/networks/subnets/forms.py:119
+msgid "Gateway IP and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:112
+msgid "Create"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:113
+#, python-format
+msgid "Created network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:114
+#, python-format
+msgid "Unable to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:130
+#, python-format
+msgid "Network \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:133
+#, python-format
+msgid "Failed to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:152
+#, python-format
+msgid "Subnet \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:155
+#, python-format
+msgid "Failed to create subnet \"%(sub)s\" for network \"%(net)s\"."
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Attached"
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Detached"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:85
+#, python-format
+msgid "Subnet %s was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:90
+#, python-format
+msgid "Failed to create subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:131
+#, python-format
+msgid "Subnet %s was successfully updated."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:136
+#, python-format
+msgid "Failed to update subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/tabs.py:42
+msgid "Unable to retrieve subnet details."
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/_detail_overview.html:3
+msgid "Network Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/detail.html:6
+msgid "Network Detail: "
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:3
+msgid "Port Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:17
+msgid "Fixed IP"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:21
+msgid "IP address:"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:22
+msgid "Subnet ID"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:28
+msgid "Mac Address"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/detail.html:3
+#: dashboards/project/networks/templates/networks/ports/detail.html:6
+msgid "Port Detail"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:3
+msgid "Subnet Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:21
+msgid "IP allocation pool"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:24
+msgid "Start"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:25
+msgid " - End"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/detail.html:3
+#: dashboards/project/networks/templates/networks/subnets/detail.html:6
+msgid "Subnet Detail"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:29
+msgid "Size (GB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:30
+msgid "Use snapshot as a source"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:49
+#, python-format
+msgid "Volume size must be equal to or greater than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:54
+msgid "Unable to load the specified snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:59
+msgid "Choose a snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:83
+#, python-format
+msgid "The volume size cannot be less than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:92
+#, python-format
+msgid ""
+"A volume of %(req)iGB cannot be created as you only have %(avail)iGB of your "
+"quota available."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:99
+msgid "You are already using all of your available volumes."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:115
+msgid "Unable to create volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:123
+msgid "Attach to Instance"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:124
+msgid "Select an instance to attach to."
+msgstr "Selecione uma instância para anexar."
+
+#: dashboards/project/volumes/forms.py:168
+msgid "Unknown instance (None)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:179
+#, python-format
+msgid "Attaching volume %(vol)s to instance %(inst)s on %(dev)s."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:188
+msgid "Unable to attach volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:212
+#, python-format
+msgid "Creating volume snapshot \"%s\""
+msgstr "Criando instantâneo volume \"%s\""
+
+#: dashboards/project/volumes/forms.py:218
+msgid "Unable to create volume snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:46
+#, fuzzy, python-format
+msgid "Unable to delete volume \"%s\". One or more snapshots depend on it."
+msgstr "Não é possível recuperar volume de instantâneos."
+
+#: dashboards/project/volumes/tables.py:66
+msgid "Edit Attachments"
+msgstr "Editar Anexos"
+
+#: dashboards/project/volumes/tables.py:93
+#, python-format
+msgid "%sGB"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:106
+#: dashboards/project/volumes/views.py:149
+msgid "Unable to retrieve attachment information."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:123
+#, python-format
+msgid "Attached to %(instance)s on %(dev)s"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:180
+msgid "Detach"
+msgstr "Separar"
+
+#: dashboards/project/volumes/tables.py:181
+msgid "Detaching"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:216
+#, python-format
+msgid "%(dev)s on instance %(instance_name)s"
+msgstr ""
+
+#: dashboards/project/volumes/tabs.py:42
+msgid "Unable to retrieve volume details."
+msgstr "Não é possível recuperar detalhes de volume."
+
+#: dashboards/project/volumes/views.py:50
+msgid "Unable to retrieve volume list."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:58
+msgid "Unable to retrieve volume/instance attachment information"
+msgstr ""
+
+#: dashboards/project/volumes/views.py:130
+#: dashboards/project/volumes/views.py:140
+msgid "Unable to retrieve volume information."
+msgstr "Não é possível recuperar informações de volume."
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:9
+#: dashboards/project/volumes/templates/volumes/attach.html:6
+msgid "Manage Volume Attachments"
+msgstr "Gerenciar Anexos de Volume"
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:13
+msgid "Attach To Instance"
+msgstr "Anexar a uma Instância"
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:22
+msgid "Attach Volume"
+msgstr "Anexar a um Volume"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:20
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:18
+msgid "Volumes are block devices that can be attached to instances."
+msgstr "Volumes são dispositivos de bloco que podem ser anexados a instâncias."
+
+#: dashboards/project/volumes/templates/volumes/_create.html:22
+msgid "Volume Quotas"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:25
+msgid "Total Gigabytes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:34
+msgid "Number of Volumes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:8
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:23
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:3
+msgid "Create Volume Snapshot"
+msgstr "Criar Instantâneo de Volume"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:3
+msgid "Volume Overview"
+msgstr "Resumo de Volume"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:34
+msgid "Attachments"
+msgstr "Anexos"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:46
+msgid "Not attached"
+msgstr "Não ligado"
+
+#: dashboards/project/volumes/templates/volumes/create.html:6
+msgid "Create a Volume"
+msgstr "Criar um volume"
+
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:6
+msgid "Create a Volume Snapshot"
+msgstr "Criar um instantâneo de volume"
+
+#: dashboards/settings/dashboard.py:24 templates/_header.html:4
+msgid "Settings"
+msgstr "Configurações"
+
+#: dashboards/settings/ec2/forms.py:36 dashboards/settings/project/forms.py:36
+msgid "Select a Project"
+msgstr "Selecione um projeto"
+
+#: dashboards/settings/ec2/forms.py:46
+msgid "Unable to retrieve tenant list."
+msgstr "Não foi possível recuperar a lista de projetos."
+
+#: dashboards/settings/ec2/forms.py:88
+msgid "Unable to fetch EC2 credentials."
+msgstr "Não foi possível obter credenciais EC2."
+
+#: dashboards/settings/ec2/forms.py:101
+#, python-format
+msgid "Error writing zipfile: %(exc)s"
+msgstr "Erro de arquivo zip escrita: %(exc)s"
+
+#: dashboards/settings/ec2/panel.py:25
+msgid "EC2 Credentials"
+msgstr "Credenciais EC2"
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:8
+#: dashboards/settings/ec2/templates/ec2/download_form.html:23
+#: dashboards/settings/ec2/templates/ec2/index.html:3
+#: dashboards/settings/ec2/templates/ec2/index.html:6
+msgid "Download EC2 Credentials"
+msgstr "Baixe Credenciais EC2"
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:18
+msgid ""
+"Clicking \"Download EC2 Credentials\" will download a zip file which "
+"includes an rc file with your access/secret keys, as well as your x509 "
+"private key and certificate."
+msgstr ""
+"Clicando em \"Baixe Credenciais EC2\" irá baixar um arquivo zip que inclui "
+"um arquivo rc com seu acesso / secret chaves, bem como a sua chave privada e "
+"certificado x509."
+
+#: dashboards/settings/project/forms.py:71
+#, python-format
+msgid "Error Downloading RC File: %s"
+msgstr "Erro ao baixar arquivo RC: %s"
+
+#: dashboards/settings/project/panel.py:25
+#: dashboards/settings/project/templates/project/_openrc.html:8
+#: dashboards/settings/project/templates/project/settings.html:3
+#: dashboards/settings/project/templates/project/settings.html:6
+msgid "OpenStack API"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:27
+msgid "Service Name"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:29
+msgid "Service Endpoint"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:33
+msgid "API Endpoints"
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:15
+msgid "Download OpenStack RC File"
+msgstr "Baixe OpenStack Arquivo RC"
+
+#: dashboards/settings/project/templates/project/_openrc.html:25
+msgid ""
+"Download the RC file for the selected project, then type \"source openrc\" "
+"in the terminal to configure your environment to communicate with OpenStack."
+msgstr ""
+"Baixe o arquivo RC para o projeto selecionado, em seguida, digite \"openrc "
+"fonte\" no terminal para configurar seu ambiente para se comunicar com "
+"OpenStack."
+
+#: dashboards/settings/project/templates/project/_openrc.html:30
+msgid "Download RC File"
+msgstr "Baixar o Arquivo RC"
+
+#: dashboards/settings/user/forms.py:57
+msgid "Settings saved."
+msgstr ""
+
+#: dashboards/settings/user/panel.py:25
+#: dashboards/settings/user/templates/user/_settings.html:8
+#: dashboards/settings/user/templates/user/settings.html:3
+#: dashboards/settings/user/templates/user/settings.html:6
+msgid "User Settings"
+msgstr "As Configurações do Usuário"
+
+#: dashboards/settings/user/templates/user/_settings.html:18
+msgid "From here you can modify dashboard settings for your user."
+msgstr ""
+
#: templates/403.html:4 templates/403.html.py:9
msgid "Forbidden"
msgstr "Proibido"
@@ -82,10 +3292,6 @@ msgstr "Proibido"
msgid "Home"
msgstr "Origem"
-#: templates/403.html:24 templates/404.html:23 templates/500.html:23
-msgid "Projects"
-msgstr "Projetos"
-
#: templates/404.html:4
msgid "Page Not Found"
msgstr "Página não Encontrada"
@@ -109,3 +3315,47 @@ msgid ""
"request again."
msgstr ""
"Ocorreu um erro inesperado ao processar o pedido. Por favor, tente novamente."
+
+#: templates/_header.html:3
+msgid "Logged in as"
+msgstr ""
+
+#: templates/_header.html:6
+msgid "Help"
+msgstr ""
+
+#: templates/_header.html:8
+msgid "Sign Out"
+msgstr ""
+
+#: test/settings.py:50
+msgid "Password must be between 8 and 18 characters."
+msgstr "A senha deve ter entre 8 e 18 caracteres."
+
+#: usage/base.py:97
+msgid "Unable to retrieve usage information."
+msgstr "Não é possível recuperar informações de uso."
+
+#: usage/base.py:100
+msgid "You are viewing data for the future, which may or may not exist."
+msgstr "Você está vendo dados para o futuro, que pode ou não existir."
+
+#: usage/tables.py:11
+msgid "Download CSV Summary"
+msgstr "Baixe Resumo CSV"
+
+#: usage/tables.py:25
+msgid "VCPU Hours"
+msgstr "VCPU Horas"
+
+#: usage/tables.py:32
+msgid "Disk GB Hours"
+msgstr "Disco GB Horas"
+
+#: usage/tables.py:40 usage/tables.py:68
+msgid "Usage Summary"
+msgstr "Resumo de Utilização"
+
+#: usage/tables.py:60
+msgid "Uptime"
+msgstr "Tempo a Ativo"
diff --git a/openstack_dashboard/locale/pt_BR/LC_MESSAGES/django.mo b/openstack_dashboard/locale/pt_BR/LC_MESSAGES/django.mo
index ee5d1894d..afb1fb22d 100644
--- a/openstack_dashboard/locale/pt_BR/LC_MESSAGES/django.mo
+++ b/openstack_dashboard/locale/pt_BR/LC_MESSAGES/django.mo
Binary files differ
diff --git a/openstack_dashboard/locale/pt_BR/LC_MESSAGES/django.po b/openstack_dashboard/locale/pt_BR/LC_MESSAGES/django.po
index f4b405e18..f7dd54a6a 100644
--- a/openstack_dashboard/locale/pt_BR/LC_MESSAGES/django.po
+++ b/openstack_dashboard/locale/pt_BR/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Horizon\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-09-18 22:18+0000\n"
+"POT-Creation-Date: 2012-10-05 19:30+0000\n"
"PO-Revision-Date: 2012-08-14 08:40+0000\n"
"Last-Translator: pauloricardomg <pauloricardomg@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,63 +18,3261 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
-#: settings.py:141
+#: settings.py:142
msgid "Bulgarian (Bulgaria)"
msgstr ""
-#: settings.py:142
+#: settings.py:143
msgid "Czech"
msgstr ""
-#: settings.py:143
+#: settings.py:144
msgid "English"
msgstr "Inglês"
-#: settings.py:144
+#: settings.py:145
msgid "Spanish"
msgstr "Espanhol"
-#: settings.py:145
+#: settings.py:146
msgid "French"
msgstr "Francês"
-#: settings.py:146
+#: settings.py:147
msgid "Italiano"
msgstr "Italiano"
-#: settings.py:147
+#: settings.py:148
msgid "Japanese"
msgstr "Japonês"
-#: settings.py:148
+#: settings.py:149
msgid "Korean (Korea)"
msgstr ""
-#: settings.py:149
+#: settings.py:150
msgid "Dutch (Netherlands)"
msgstr ""
-#: settings.py:150
+#: settings.py:151
msgid "Polish"
msgstr "Polonês"
-#: settings.py:151
+#: settings.py:152
msgid "Portuguese"
msgstr "Português"
-#: settings.py:152
+#: settings.py:153
#, fuzzy
msgid "Portuguese (Brazil)"
msgstr "Português"
-#: settings.py:153
+#: settings.py:154
msgid "Simplified Chinese"
msgstr "Chinês Simplificado"
-#: settings.py:154
+#: settings.py:155
msgid "Traditional Chinese"
msgstr "Chinês Tradicional"
+#: api/keystone.py:56
+#, python-format
+msgid "%(type)s (%(backend)s backend)"
+msgstr "%(type)s (%(backend)s backend)"
+
+#: api/nova.py:191
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(group)s"
+msgstr "PERMITIR %(from)s:%(to)s a partir de %(group)s"
+
+#: api/nova.py:196
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(cidr)s"
+msgstr "PERMITIR %(from)s:%(to)s a partir de %(cidr)s"
+
+#: api/nova.py:532
+msgid "Unknown instance"
+msgstr "Instância desconhecida"
+
+#: api/swift.py:217
+msgid "Unicode is not currently supported for object copy."
+msgstr "Unicode não é suportado para cópia de objeto."
+
+#: dashboards/admin/dashboard.py:24
+msgid "System Panel"
+msgstr "Painel do Sistema"
+
+#: dashboards/admin/dashboard.py:30
+msgid "Admin"
+msgstr "Administrador"
+
+#: dashboards/admin/flavors/forms.py:36 dashboards/admin/networks/forms.py:34
+#: dashboards/admin/networks/forms.py:69
+#: dashboards/admin/networks/ports/forms.py:40
+#: dashboards/admin/networks/ports/forms.py:72
+#: dashboards/admin/networks/ports/tables.py:73
+#: dashboards/admin/networks/subnets/tables.py:70
+#: dashboards/admin/projects/tables.py:87
+#: dashboards/admin/projects/workflows.py:71
+#: dashboards/admin/services/tables.py:38
+#: dashboards/admin/volumes/tables.py:10
+#: dashboards/project/access_and_security/security_groups/forms.py:36
+#: dashboards/project/access_and_security/security_groups/tables.py:58
+#: dashboards/project/images_and_snapshots/images/forms.py:40
+#: dashboards/project/images_and_snapshots/images/forms.py:115
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:9
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:10
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:77
+#: dashboards/project/instances/templates/instances/_detail_overview.html:9
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:9
+#: dashboards/project/networks/forms.py:37
+#: dashboards/project/networks/tables.py:94
+#: dashboards/project/networks/ports/tables.py:40
+#: dashboards/project/networks/subnets/forms.py:43
+#: dashboards/project/networks/subnets/forms.py:102
+#: dashboards/project/networks/subnets/tables.py:82
+#: dashboards/project/networks/templates/networks/_detail_overview.html:7
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:9
+#: dashboards/project/volumes/tables.py:144
+#: dashboards/project/volumes/tables.py:164
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:9
+msgid "Name"
+msgstr "Nome"
+
+#: dashboards/admin/flavors/forms.py:37 dashboards/admin/flavors/tables.py:41
+#: dashboards/admin/projects/workflows.py:39
+#: dashboards/project/instances/templates/instances/_detail_overview.html:26
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:10
+#: usage/tables.py:19
+msgid "VCPUs"
+msgstr "VCPUs"
+
+#: dashboards/admin/flavors/forms.py:38
+msgid "RAM MB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:39
+msgid "Root Disk GB"
+msgstr "Disco Root GB"
+
+#: dashboards/admin/flavors/forms.py:40
+msgid "Ephemeral Disk GB"
+msgstr "Disco temporário GB"
+
+#: dashboards/admin/flavors/forms.py:50
+msgid "Unable to get unique ID for new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:67
+#, python-format
+msgid "Created flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:71
+msgid "Unable to create flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:92
+#, python-format
+msgid "Updated flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:96
+msgid "Unable to update flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/panel.py:29 dashboards/admin/flavors/tables.py:15
+#: dashboards/admin/flavors/tables.py:52
+#: dashboards/admin/flavors/templates/flavors/index.html:3
+#: dashboards/admin/flavors/templates/flavors/index.html:6
+msgid "Flavors"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:14
+#: dashboards/project/instances/workflows.py:177
+#: dashboards/project/instances/templates/instances/_detail_overview.html:22
+msgid "Flavor"
+msgstr "Sabor"
+
+#: dashboards/admin/flavors/tables.py:23
+#: dashboards/admin/flavors/templates/flavors/_create.html:8
+#: dashboards/admin/flavors/templates/flavors/_create.html:23
+#: dashboards/admin/flavors/templates/flavors/create.html:3
+#: dashboards/admin/flavors/templates/flavors/create.html:6
+msgid "Create Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:30
+#: dashboards/admin/flavors/templates/flavors/_edit.html:8
+#: dashboards/admin/flavors/templates/flavors/edit.html:3
+#: dashboards/admin/flavors/templates/flavors/edit.html:6
+msgid "Edit Flavor"
+msgstr "Editar Sabor"
+
+#: dashboards/admin/flavors/tables.py:36
+#, python-format
+msgid "%sMB"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:40
+msgid "Flavor Name"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:43
+#: dashboards/project/instances/templates/instances/_detail_overview.html:24
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: usage/tables.py:22
+msgid "RAM"
+msgstr "RAM"
+
+#: dashboards/admin/flavors/tables.py:45
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+msgid "Root Disk"
+msgstr "Disco Root"
+
+#: dashboards/admin/flavors/tables.py:47
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+msgid "Ephemeral Disk"
+msgstr "Disco Temporário"
+
+#: dashboards/admin/flavors/views.py:49
+msgid "Unable to retrieve flavor list."
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:76
+msgid "Unable to retrieve flavor data."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:17
+#: dashboards/admin/flavors/templates/flavors/_edit.html:17
+#: dashboards/admin/images/templates/images/_update.html:17
+#: dashboards/admin/networks/templates/networks/_create.html:17
+#: dashboards/admin/networks/templates/networks/ports/_create.html:17
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:17
+#: dashboards/admin/projects/tables.py:89
+#: dashboards/admin/projects/workflows.py:74
+#: dashboards/admin/projects/templates/projects/_add_user.html:17
+#: dashboards/admin/projects/templates/projects/_create.html:17
+#: dashboards/admin/projects/templates/projects/_create_user.html:17
+#: dashboards/admin/projects/templates/projects/_quotas.html:16
+#: dashboards/admin/projects/templates/projects/_update.html:17
+#: dashboards/admin/users/templates/users/_create.html:16
+#: dashboards/admin/users/templates/users/_update.html:16
+#: dashboards/project/access_and_security/security_groups/forms.py:38
+#: dashboards/project/access_and_security/security_groups/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:17
+#: dashboards/project/containers/templates/containers/_copy.html:16
+#: dashboards/project/containers/templates/containers/_create.html:16
+#: dashboards/project/containers/templates/containers/_upload.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/_create.html:16
+#: dashboards/project/networks/templates/networks/subnets/_create.html:17
+#: dashboards/project/volumes/forms.py:28
+#: dashboards/project/volumes/forms.py:195
+#: dashboards/project/volumes/tables.py:147
+#: dashboards/project/volumes/templates/volumes/_create.html:18
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:17
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:14
+msgid "Description"
+msgstr "Descrição"
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:18
+msgid "From here you can define the sizing of a new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:24
+#: dashboards/admin/flavors/templates/flavors/_edit.html:25
+#: dashboards/admin/images/templates/images/_update.html:24
+#: dashboards/admin/networks/templates/networks/_create.html:24
+#: dashboards/admin/networks/templates/networks/_update.html:23
+#: dashboards/admin/networks/templates/networks/ports/_create.html:24
+#: dashboards/admin/networks/templates/networks/ports/_update.html:28
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:24
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:32
+#: dashboards/admin/projects/templates/projects/_add_user.html:24
+#: dashboards/admin/projects/templates/projects/_create.html:24
+#: dashboards/admin/projects/templates/projects/_create_user.html:24
+#: dashboards/admin/projects/templates/projects/_quotas.html:23
+#: dashboards/admin/projects/templates/projects/_update.html:24
+#: dashboards/admin/users/templates/users/_create.html:23
+#: dashboards/admin/users/templates/users/_update.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:32
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:20
+#: dashboards/project/containers/templates/containers/_copy.html:23
+#: dashboards/project/containers/templates/containers/_create.html:23
+#: dashboards/project/containers/templates/containers/_upload.html:24
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:32
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:24
+#: dashboards/project/instances/templates/instances/_update.html:23
+#: dashboards/project/networks/templates/networks/_create.html:23
+#: dashboards/project/networks/templates/networks/_update.html:23
+#: dashboards/project/networks/templates/networks/subnets/_create.html:24
+#: dashboards/project/networks/templates/networks/subnets/_update.html:32
+#: dashboards/project/volumes/templates/volumes/_attach.html:24
+#: dashboards/project/volumes/templates/volumes/_create.html:56
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:24
+#: dashboards/settings/ec2/templates/ec2/download_form.html:24
+#: dashboards/settings/project/templates/project/_openrc.html:31
+#: dashboards/settings/user/templates/user/_settings.html:24
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:18
+msgid "From here you can alter the sizing of the current flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:19
+msgid ""
+"Note: this will not affect the resources allocated to any existing instances "
+"using this flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:24
+#: dashboards/admin/projects/workflows.py:270
+#: dashboards/settings/user/templates/user/_settings.html:23
+msgid "Save"
+msgstr "Salvar"
+
+#: dashboards/admin/images/panel.py:29 dashboards/admin/images/tables.py:44
+#: dashboards/admin/images/templates/images/index.html:3
+#: dashboards/admin/images/templates/images/index.html:6
+#: dashboards/project/images_and_snapshots/images/tables.py:47
+#: dashboards/project/images_and_snapshots/images/tables.py:132
+msgid "Images"
+msgstr "Imagems"
+
+#: dashboards/admin/images/tables.py:40
+#: dashboards/project/images_and_snapshots/images/tables.py:113
+#: dashboards/project/instances/templates/instances/_detail_overview.html:74
+msgid "Image Name"
+msgstr "Nome de Imagem"
+
+#: dashboards/admin/images/views.py:55
+msgid "Unable to retrieve image list."
+msgstr "Não foi possível obter a lista de imagens."
+
+#: dashboards/admin/images/templates/images/_update.html:8
+#: dashboards/admin/images/templates/images/_update.html:23
+#: dashboards/admin/images/templates/images/update.html:4
+#: dashboards/admin/images/templates/images/update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:22
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:6
+msgid "Update Image"
+msgstr "Atualizar Imagem."
+
+#: dashboards/admin/images/templates/images/_update.html:18
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:17
+msgid "From here you can modify different properties of an image."
+msgstr ""
+"A partir daqui você pode modificar diferentes propriedades de uma imagem."
+
+#: dashboards/admin/instances/panel.py:29
+#: dashboards/admin/instances/tables.py:94
+#: dashboards/admin/instances/templates/instances/index.html:3
+#: dashboards/admin/projects/workflows.py:40
+#: dashboards/project/instances/panel.py:25
+#: dashboards/project/instances/tables.py:70
+#: dashboards/project/instances/tables.py:90
+#: dashboards/project/instances/tables.py:107
+#: dashboards/project/instances/tables.py:136
+#: dashboards/project/instances/tables.py:313
+#: dashboards/project/instances/templates/instances/index.html:3
+#: dashboards/project/instances/templates/instances/index.html:6
+msgid "Instances"
+msgstr "Instâncias"
+
+#: dashboards/admin/instances/tables.py:60 usage/tables.py:30
+msgid "Project Name"
+msgstr "Nome de Projeto"
+
+#: dashboards/admin/instances/tables.py:67
+#: dashboards/admin/services/tables.py:40
+msgid "Host"
+msgstr "Servidor"
+
+#: dashboards/admin/instances/tables.py:71
+#: dashboards/project/instances/tables.py:290
+#: dashboards/project/instances/workflows.py:176 usage/tables.py:57
+msgid "Instance Name"
+msgstr "Nome da instância"
+
+#: dashboards/admin/instances/tables.py:72
+#: dashboards/project/access_and_security/floating_ips/tables.py:111
+#: dashboards/project/access_and_security/floating_ips/workflows.py:32
+#: dashboards/project/access_and_security/floating_ips/workflows.py:39
+#: dashboards/project/instances/tables.py:291
+msgid "IP Address"
+msgstr "Endereço IP"
+
+#: dashboards/admin/instances/tables.py:74
+#: dashboards/project/containers/tables.py:256
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:30
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:37
+#: dashboards/project/instances/tables.py:293
+#: dashboards/project/volumes/tables.py:150
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:26
+msgid "Size"
+msgstr "Tamanho"
+
+#: dashboards/admin/instances/tables.py:79
+#: dashboards/admin/networks/tables.py:74
+#: dashboards/admin/networks/ports/tables.py:77
+#: dashboards/project/images_and_snapshots/images/tables.py:119
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:13
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:18
+#: dashboards/project/instances/tables.py:298
+#: dashboards/project/instances/templates/instances/_detail_overview.html:13
+#: dashboards/project/networks/tables.py:100
+#: dashboards/project/networks/ports/tables.py:44
+#: dashboards/project/networks/templates/networks/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:30
+#: dashboards/project/volumes/tables.py:154
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:17
+msgid "Status"
+msgstr "Condição"
+
+#: dashboards/admin/instances/tables.py:83
+#: dashboards/project/instances/tables.py:302
+msgid "Task"
+msgstr "Tarefa"
+
+#: dashboards/admin/instances/tables.py:90
+#: dashboards/project/instances/tables.py:309
+msgid "Power State"
+msgstr "Estado de energia"
+
+#: dashboards/admin/instances/views.py:49
+#: dashboards/project/access_and_security/views.py:76
+#: dashboards/project/access_and_security/floating_ips/workflows.py:65
+msgid "Unable to retrieve instance list."
+msgstr "Não foi possível recuperar a lista de instâncias."
+
+#: dashboards/admin/instances/views.py:63
+#: dashboards/admin/networks/views.py:48
+msgid "Unable to retrieve instance tenant information."
+msgstr "Não foi possível obter informações sobre a instância de tenant"
+
+#: dashboards/admin/instances/views.py:80
+#: dashboards/project/instances/views.py:82
+msgid "Unable to retrieve instance size information."
+msgstr "Não é possível recuperar informações de tamanho instância."
+
+#: dashboards/admin/instances/templates/instances/index.html:6
+msgid "All Instances"
+msgstr "Todas as Instâncias"
+
+#: dashboards/admin/networks/forms.py:36
+#: dashboards/admin/networks/tables.py:67
+#: dashboards/admin/projects/tables.py:65 dashboards/project/dashboard.py:40
+#: dashboards/project/instances/workflows.py:38
+msgid "Project"
+msgstr "Projeto"
+
+#: dashboards/admin/networks/forms.py:37 dashboards/admin/networks/forms.py:74
+#: dashboards/admin/networks/tables.py:72
+#: dashboards/project/networks/tables.py:98
+#: dashboards/project/networks/templates/networks/_detail_overview.html:17
+msgid "Shared"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:46 dashboards/admin/users/forms.py:42
+msgid "Select a project"
+msgstr "Selecionar um projeto"
+
+#: dashboards/admin/networks/forms.py:58
+#, python-format
+msgid "Network %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:64
+#, python-format
+msgid "Failed to create network %s"
+msgstr "Falha ao criar rede %s"
+
+#: dashboards/admin/networks/forms.py:71
+#: dashboards/admin/networks/templates/networks/ports/_update.html:12
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:12
+#: dashboards/admin/users/forms.py:114
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:11
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:12
+#: dashboards/project/instances/templates/instances/_detail_overview.html:11
+#: dashboards/project/networks/forms.py:39
+#: dashboards/project/networks/templates/networks/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_update.html:12
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:11
+msgid "ID"
+msgstr "ID"
+
+#: dashboards/admin/networks/forms.py:82
+#: dashboards/project/networks/forms.py:48
+#, python-format
+msgid "Network %s was successfully updated."
+msgstr "Rede %s foi atualizado com sucesso."
+
+#: dashboards/admin/networks/forms.py:87
+#: dashboards/project/networks/forms.py:53
+#, python-format
+msgid "Failed to update network %s"
+msgstr "Falha ao atualizar rede %s"
+
+#: dashboards/admin/networks/panel.py:25
+#: dashboards/admin/networks/tables.py:35
+#: dashboards/admin/networks/tables.py:80
+#: dashboards/admin/networks/templates/networks/index.html:3
+#: dashboards/admin/networks/templates/networks/index.html:6
+#: dashboards/project/instances/workflows.py:412
+#: dashboards/project/networks/panel.py:25
+#: dashboards/project/networks/tables.py:44
+#: dashboards/project/networks/tables.py:106
+#: dashboards/project/networks/templates/networks/index.html:3
+#: dashboards/project/networks/templates/networks/index.html:6
+msgid "Networks"
+msgstr "Redes"
+
+#: dashboards/admin/networks/tables.py:34
+#: dashboards/project/networks/tables.py:43
+#: dashboards/project/networks/templates/networks/subnets/index.html:3
+#: dashboards/project/networks/templates/networks/subnets/index.html:6
+msgid "Network"
+msgstr "Rede"
+
+#: dashboards/admin/networks/tables.py:41
+#: dashboards/project/networks/tables.py:59
+#, python-format
+msgid "Failed to delete network %s"
+msgstr "Falha ao apagar rede %s"
+
+#: dashboards/admin/networks/tables.py:49
+#: dashboards/admin/networks/templates/networks/_create.html:8
+#: dashboards/admin/networks/templates/networks/_create.html:23
+#: dashboards/admin/networks/templates/networks/create.html:3
+#: dashboards/admin/networks/templates/networks/create.html:6
+#: dashboards/project/networks/tables.py:67
+#: dashboards/project/networks/workflows.py:111
+#: dashboards/project/networks/templates/networks/_create.html:7
+#: dashboards/project/networks/templates/networks/_create.html:22
+#: dashboards/project/networks/templates/networks/create.html:3
+#: dashboards/project/networks/templates/networks/create.html:6
+msgid "Create Network"
+msgstr "Criar Rede"
+
+#: dashboards/admin/networks/tables.py:56
+#: dashboards/admin/networks/templates/networks/_update.html:7
+#: dashboards/project/networks/tables.py:74
+#: dashboards/project/networks/templates/networks/_update.html:7
+msgid "Edit Network"
+msgstr "Editar Rede"
+
+#: dashboards/admin/networks/tables.py:68
+#: dashboards/admin/networks/ports/forms.py:33
+#: dashboards/project/networks/subnets/forms.py:35
+msgid "Network Name"
+msgstr "Nome de Rede"
+
+#: dashboards/admin/networks/tables.py:71
+#: dashboards/project/networks/tables.py:97
+msgid "Subnets Associated"
+msgstr "Sub-redes Associadas"
+
+#: dashboards/admin/networks/tables.py:76
+#: dashboards/admin/networks/ports/tables.py:79
+#: dashboards/project/networks/tables.py:102
+#: dashboards/project/networks/ports/tables.py:46
+#: dashboards/project/networks/templates/networks/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:32
+msgid "Admin State"
+msgstr "Estado de Administração"
+
+#: dashboards/admin/networks/views.py:60
+#: dashboards/project/networks/views.py:52
+msgid "Network list can not be retrieved."
+msgstr "Lista de rede não pode ser recuperada."
+
+#: dashboards/admin/networks/views.py:91
+#: dashboards/project/networks/views.py:109
+msgid "Subnet list can not be retrieved."
+msgstr "Lista de sub-rede não pode ser recuperada."
+
+#: dashboards/admin/networks/views.py:103
+#: dashboards/project/networks/views.py:121
+msgid "Port list can not be retrieved."
+msgstr "Lista de portas não podem ser recuperadas."
+
+#: dashboards/admin/networks/views.py:118
+#: dashboards/project/networks/views.py:134
+#: dashboards/project/networks/subnets/tables.py:96
+#, python-format
+msgid "Unable to retrieve details for network \"%s\"."
+msgstr "Não foi possível obter detalhes de rede \"%s\"."
+
+#: dashboards/admin/networks/ports/forms.py:36
+#: dashboards/project/networks/subnets/forms.py:39
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:13
+msgid "Network ID"
+msgstr "Rede ID"
+
+#: dashboards/admin/networks/ports/forms.py:42
+#: dashboards/admin/networks/ports/forms.py:74
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:34
+msgid "Device ID"
+msgstr "Identificador do Dispositivo"
+
+#: dashboards/admin/networks/ports/forms.py:54
+#, python-format
+msgid "Port %s was successfully created."
+msgstr "Porta %s criada com sucesso."
+
+#: dashboards/admin/networks/ports/forms.py:59
+#, python-format
+msgid "Failed to create a port for network %s"
+msgstr "Falha ao criar uma porta para a rede %s"
+
+#: dashboards/admin/networks/ports/forms.py:84
+#, python-format
+msgid "Port %s was successfully updated."
+msgstr "Porta %s atualizada com sucesso."
+
+#: dashboards/admin/networks/ports/forms.py:89
+#, python-format
+msgid "Failed to update port %s"
+msgstr "Falha ao atualizar porta %s"
+
+#: dashboards/admin/networks/ports/tables.py:34
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:6
+msgid "Port"
+msgstr "Porta"
+
+#: dashboards/admin/networks/ports/tables.py:35
+#: dashboards/admin/networks/ports/tables.py:83
+#: dashboards/project/networks/ports/tables.py:53
+msgid "Ports"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:41
+#: dashboards/admin/networks/subnets/tables.py:39
+#: dashboards/project/networks/subnets/tables.py:51
+#, python-format
+msgid "Failed to delete subnet %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:51
+#: dashboards/admin/networks/templates/networks/ports/_create.html:8
+#: dashboards/admin/networks/templates/networks/ports/_create.html:23
+#: dashboards/admin/networks/templates/networks/ports/create.html:3
+#: dashboards/admin/networks/templates/networks/ports/create.html:6
+msgid "Create Port"
+msgstr "Criar Porta"
+
+#: dashboards/admin/networks/ports/tables.py:62
+#: dashboards/admin/networks/templates/networks/ports/_update.html:7
+msgid "Edit Port"
+msgstr "Alterar Porta"
+
+#: dashboards/admin/networks/ports/tables.py:75
+#: dashboards/project/networks/ports/tables.py:42
+msgid "Fixed IPs"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:76
+#: dashboards/project/networks/ports/tables.py:43
+msgid "Device Attached"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tabs.py:32
+#: dashboards/admin/overview/panel.py:29
+#: dashboards/admin/overview/templates/overview/usage.html:6
+#: dashboards/project/images_and_snapshots/images/tabs.py:27
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:27
+#: dashboards/project/instances/tabs.py:26
+#: dashboards/project/networks/ports/tabs.py:32
+#: dashboards/project/networks/subnets/tabs.py:32
+#: dashboards/project/overview/panel.py:29
+#: dashboards/project/overview/templates/overview/usage.html:6
+#: dashboards/project/volumes/tabs.py:27
+msgid "Overview"
+msgstr "Visão Global"
+
+#: dashboards/admin/networks/ports/tabs.py:42
+#: dashboards/project/networks/ports/tabs.py:42
+msgid "Unable to retrieve port details."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:49
+#: dashboards/admin/networks/subnets/views.py:49
+#: dashboards/project/networks/subnets/views.py:54
+msgid "Unable to retrieve network."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:82
+msgid "Unable to retrieve port details"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/forms.py:43
+#, python-format
+msgid "Failed to retrieve network %s for a subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:32
+#: dashboards/project/networks/subnets/tables.py:44
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:6
+msgid "Subnet"
+msgstr "Sub-rede"
+
+#: dashboards/admin/networks/subnets/tables.py:33
+#: dashboards/admin/networks/subnets/tables.py:81
+#: dashboards/project/networks/subnets/tables.py:45
+#: dashboards/project/networks/subnets/tables.py:104
+msgid "Subnets"
+msgstr "Sub-redes"
+
+#: dashboards/admin/networks/subnets/tables.py:49
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:8
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:23
+#: dashboards/admin/networks/templates/networks/subnets/create.html:3
+#: dashboards/admin/networks/templates/networks/subnets/create.html:6
+#: dashboards/project/networks/workflows.py:53
+#: dashboards/project/networks/subnets/tables.py:61
+#: dashboards/project/networks/templates/networks/subnets/_create.html:8
+#: dashboards/project/networks/templates/networks/subnets/_create.html:23
+#: dashboards/project/networks/templates/networks/subnets/create.html:3
+#: dashboards/project/networks/templates/networks/subnets/create.html:6
+msgid "Create Subnet"
+msgstr "Criar sub-rede"
+
+#: dashboards/admin/networks/subnets/tables.py:60
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:7
+#: dashboards/project/networks/subnets/tables.py:72
+#: dashboards/project/networks/templates/networks/subnets/_update.html:7
+msgid "Edit Subnet"
+msgstr "Editar Sub-rede"
+
+#: dashboards/admin/networks/subnets/tables.py:72
+#: dashboards/project/access_and_security/security_groups/forms.py:91
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:15
+msgid "CIDR"
+msgstr "CIDR"
+
+#: dashboards/admin/networks/subnets/tables.py:73
+#: dashboards/project/networks/workflows.py:66
+#: dashboards/project/networks/subnets/forms.py:53
+#: dashboards/project/networks/subnets/tables.py:85
+msgid "IP Version"
+msgstr "IP Versão"
+
+#: dashboards/admin/networks/subnets/tables.py:74
+#: dashboards/project/networks/subnets/forms.py:54
+#: dashboards/project/networks/subnets/forms.py:104
+#: dashboards/project/networks/subnets/tables.py:86
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:19
+msgid "Gateway IP"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/views.py:82
+#: dashboards/project/networks/subnets/views.py:86
+msgid "Unable to retrieve subnet details"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_create.html:18
+#: dashboards/project/networks/templates/networks/_create.html:17
+msgid "Select a name for your network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:16
+#: dashboards/admin/networks/templates/networks/ports/_update.html:21
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:25
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:17
+#: dashboards/project/instances/templates/instances/_update.html:16
+#: dashboards/project/networks/templates/networks/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_update.html:25
+#: dashboards/settings/ec2/templates/ec2/download_form.html:17
+#: dashboards/settings/project/templates/project/_openrc.html:24
+#: dashboards/settings/user/templates/user/_settings.html:17
+msgid "Description:"
+msgstr "Descrição:"
+
+#: dashboards/admin/networks/templates/networks/_update.html:17
+#: dashboards/project/networks/templates/networks/_update.html:17
+msgid "You may update the editable properties of your network here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:22
+#: dashboards/admin/networks/templates/networks/ports/_update.html:27
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:31
+#: dashboards/project/instances/templates/instances/_update.html:22
+#: dashboards/project/networks/templates/networks/_update.html:22
+#: dashboards/project/networks/templates/networks/subnets/_update.html:31
+msgid "Save Changes"
+msgstr "Salvar Alterações"
+
+#: dashboards/admin/networks/templates/networks/update.html:3
+#: dashboards/admin/networks/templates/networks/update.html:6
+#: dashboards/project/networks/templates/networks/update.html:3
+#: dashboards/project/networks/templates/networks/update.html:6
+msgid "Update Network"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_create.html:18
+msgid ""
+"You can create a port for the network. If you specify device ID to be "
+"attached, the device specified will be attached to the port created."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_update.html:22
+msgid "You may update the editable properties of your port here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/update.html:3
+#: dashboards/admin/networks/templates/networks/ports/update.html:6
+msgid "Update Port"
+msgstr "Atualizar Porta"
+
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:18
+#: dashboards/project/networks/templates/networks/subnets/_create.html:18
+msgid ""
+"You can create a subnet for the network. Any network address can be "
+"specified unless the network address does not overlap other subnets in the "
+"network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:14
+#: dashboards/project/networks/workflows.py:58
+#: dashboards/project/networks/subnets/forms.py:45
+#: dashboards/project/networks/subnets/tables.py:84
+#: dashboards/project/networks/templates/networks/subnets/_update.html:14
+msgid "Network Address"
+msgstr "Endereço de Rede"
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:17
+#: dashboards/project/networks/templates/networks/subnets/_update.html:16
+msgid "IP version"
+msgstr "Versão do IP"
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:26
+#: dashboards/project/networks/templates/networks/subnets/_update.html:26
+msgid "You may update the editable properties of your subnet here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/index.html:3
+#: dashboards/admin/networks/templates/networks/subnets/index.html:6
+#: dashboards/project/networks/templates/networks/detail.html:3
+msgid "Network Detail"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/update.html:3
+#: dashboards/admin/networks/templates/networks/subnets/update.html:6
+#: dashboards/project/networks/templates/networks/subnets/update.html:3
+#: dashboards/project/networks/templates/networks/subnets/update.html:6
+msgid "Update Subnet"
+msgstr "Atualizar Sub-rede"
+
+#: dashboards/admin/overview/templates/overview/usage.html:3
+msgid "Usage Overview"
+msgstr "Resumo de utilização"
+
+#: dashboards/admin/overview/templates/overview/usage.html:12
+msgid "Monitoring"
+msgstr "Monitorando"
+
+#: dashboards/admin/projects/panel.py:29
+#: dashboards/admin/projects/tables.py:66
+#: dashboards/admin/projects/tables.py:95
+#: dashboards/admin/projects/templates/projects/index.html:8
+#: templates/403.html:24 templates/404.html:23 templates/500.html:23
+msgid "Projects"
+msgstr "Projetos"
+
+#: dashboards/admin/projects/tables.py:19
+msgid "Modify Users"
+msgstr "Modificar usuários"
+
+#: dashboards/admin/projects/tables.py:32
+msgid "View Usage"
+msgstr "Ver Uso"
+
+#: dashboards/admin/projects/tables.py:39
+#: dashboards/admin/projects/templates/projects/_create.html:8
+#: dashboards/admin/projects/templates/projects/_create.html:23
+#: dashboards/admin/projects/templates/projects/create.html:6
+msgid "Create Project"
+msgstr "Criar Projeto"
+
+#: dashboards/admin/projects/tables.py:46
+#: dashboards/admin/projects/workflows.py:269
+#: dashboards/admin/projects/templates/projects/update.html:3
+#: dashboards/admin/projects/templates/projects/update.html:6
+msgid "Edit Project"
+msgstr "Editar Projeto"
+
+#: dashboards/admin/projects/tables.py:90
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:60
+#: dashboards/project/networks/templates/networks/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:15
+msgid "Project ID"
+msgstr "Projeto ID"
+
+#: dashboards/admin/projects/tables.py:91
+#: dashboards/admin/projects/workflows.py:76
+#: dashboards/admin/projects/workflows.py:251
+#: dashboards/admin/services/tables.py:42 dashboards/admin/users/tables.py:40
+#: dashboards/admin/users/tables.py:115
+msgid "Enabled"
+msgstr "Habilitado"
+
+#: dashboards/admin/projects/tables.py:104
+msgid "Remove"
+msgstr "Remover"
+
+#: dashboards/admin/projects/tables.py:105
+msgid "Removed"
+msgstr "Removido"
+
+#: dashboards/admin/projects/tables.py:106 dashboards/admin/users/tables.py:41
+#: dashboards/admin/users/tables.py:75
+#: dashboards/project/instances/workflows.py:39
+msgid "User"
+msgstr "Usuário"
+
+#: dashboards/admin/projects/tables.py:107 dashboards/admin/users/panel.py:29
+#: dashboards/admin/users/tables.py:42 dashboards/admin/users/tables.py:76
+#: dashboards/admin/users/tables.py:122
+#: dashboards/admin/users/templates/users/index.html:8
+msgid "Users"
+msgstr "Usuários"
+
+#: dashboards/admin/projects/tables.py:125
+msgid "Unable to retrieve role information."
+msgstr "Não é possível recuperar informações de função."
+
+#: dashboards/admin/projects/tables.py:130
+msgid "Roles"
+msgstr "Funções"
+
+#: dashboards/admin/projects/tables.py:134
+msgid "Users For Project"
+msgstr "Usuários por Projeto"
+
+#: dashboards/admin/projects/tables.py:142
+msgid "Add To Project"
+msgstr "Adicionar ao Porjeto"
+
+#: dashboards/admin/projects/tables.py:154
+msgid "Add New Users"
+msgstr "Adicionar Novos Usuários"
+
+#: dashboards/admin/projects/views.py:67
+msgid "Unable to retrieve project information."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:87
+msgid "Unable to retrieve project list."
+msgstr "Não foi possível obter a lista de projeto."
+
+#: dashboards/admin/projects/views.py:110
+msgid "Unable to retrieve users."
+msgstr "Não foi possível obter os usuários."
+
+#: dashboards/admin/projects/views.py:154
+msgid "Unable to retrieve default quota values."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:182
+msgid "Unable to retrieve project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:37
+msgid "Injected File Content Bytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:38
+msgid "Metadata Items"
+msgstr "Items de metadados"
+
+#: dashboards/admin/projects/workflows.py:41
+msgid "Injected Files"
+msgstr "Arquivos injetados"
+
+#: dashboards/admin/projects/workflows.py:44
+#: dashboards/admin/volumes/panel.py:9 dashboards/admin/volumes/tables.py:15
+#: dashboards/admin/volumes/templates/volumes/index.html:3
+#: dashboards/admin/volumes/templates/volumes/index.html:6
+#: dashboards/project/volumes/panel.py:25
+#: dashboards/project/volumes/tables.py:38
+#: dashboards/project/volumes/tables.py:171
+#: dashboards/project/volumes/tables.py:183
+#: dashboards/project/volumes/templates/volumes/index.html:3
+#: dashboards/project/volumes/templates/volumes/index.html:6
+msgid "Volumes"
+msgstr "Volumes"
+
+#: dashboards/admin/projects/workflows.py:45
+msgid "Gigabytes"
+msgstr "Gigabytes"
+
+#: dashboards/admin/projects/workflows.py:46
+msgid "RAM (MB)"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:47
+#: dashboards/project/access_and_security/floating_ips/tables.py:50
+#: dashboards/project/access_and_security/floating_ips/tables.py:128
+msgid "Floating IPs"
+msgstr "IPs Flutuantes"
+
+#: dashboards/admin/projects/workflows.py:50
+msgid "Quota"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:52
+msgid "From here you can set quotas (max limits) for the project."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:81
+#: dashboards/admin/projects/workflows.py:254
+msgid "Project Info"
+msgstr "Informação do Projeto"
+
+#: dashboards/admin/projects/workflows.py:82
+#: dashboards/admin/projects/templates/projects/_create.html:18
+msgid "From here you can create a new project to organize users."
+msgstr "Aqui você pode criar um projeto para organizar usuários"
+
+#: dashboards/admin/projects/workflows.py:101
+msgid "Unable to retrieve user list. Please try again later."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:155
+#: dashboards/admin/projects/templates/projects/_update_members.html:16
+msgid "Project Members"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:169
+#: dashboards/admin/users/views.py:47
+msgid "Unable to retrieve user list."
+msgstr "Não foi possível obter a lista de usuários."
+
+#: dashboards/admin/projects/workflows.py:180
+msgid "Add Project"
+msgstr "Adicionar Projeto"
+
+#: dashboards/admin/projects/workflows.py:181
+msgid "Finish"
+msgstr "Finalizar"
+
+#: dashboards/admin/projects/workflows.py:182
+#, python-format
+msgid "Created new project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:183
+#, python-format
+msgid "Unable to create project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:227
+#, python-format
+msgid "Failed to add %s project members and set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:246
+msgid "Unable to set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:256
+msgid "From here you can edit the project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:271
+#, python-format
+msgid "Modified project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:272
+#, python-format
+msgid "Unable to modify project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:342
+#, python-format
+msgid "Failed to modify %s project members and update project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:363
+msgid ""
+"Modified project information and members, but unable to modify project "
+"quotas."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:8
+#: dashboards/admin/projects/templates/projects/add_user.html:3
+#: dashboards/admin/projects/templates/projects/add_user.html:6
+msgid "Add User To Project"
+msgstr "Adicionar Usuário ao Projeto"
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:18
+msgid "Select the user role for the project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:23
+msgid "Add"
+msgstr "Adicionar"
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:7
+#, python-format
+msgid "Create User for project '%(tenant_name)s'."
+msgstr "Criar usuário para projeto '%(tenant_name)s'."
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:18
+msgid "From here you can create a new user to add to this project."
+msgstr "Aqui você pode criar um novo usuário para adicionar neste projeto."
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:23
+#: dashboards/admin/users/tables.py:20
+#: dashboards/admin/users/templates/users/_create.html:7
+#: dashboards/admin/users/templates/users/_create.html:22
+#: dashboards/admin/users/templates/users/create.html:7
+msgid "Create User"
+msgstr "Criar Usuário"
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:7
+#: dashboards/admin/projects/templates/projects/_quotas.html:22
+msgid "Update Quota"
+msgstr "Atualizar Quota"
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:17
+#, python-format
+msgid ""
+"From here you can edit quotas (max limits) for the project %(tenant.name)s."
+msgstr ""
+"Aqui você pode editar quotas (limites máx.) para o projeto %(tenant.name)s."
+
+#: dashboards/admin/projects/templates/projects/_update.html:8
+#: dashboards/admin/projects/templates/projects/_update.html:23
+#: dashboards/admin/projects/templates/projects/quotas.html:6
+msgid "Update Project"
+msgstr "Atualizar Projeto"
+
+#: dashboards/admin/projects/templates/projects/_update.html:18
+msgid "From here you can edit a project."
+msgstr "Aqui você pode editar um projeto."
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:7
+msgid ""
+"From here you can add and remove members to this project from the list of "
+"all available users."
+msgstr ""
+"Aqui você pode adicionar e remover membros deste projeto a partir da lista "
+"de usuários disponíveis."
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:10
+msgid "All Users"
+msgstr "Todos Usuários"
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:25
+#: dashboards/admin/projects/templates/projects/_update_members.html:32
+msgid "No users found."
+msgstr "Nenhum usuário encontrado."
+
+#: dashboards/admin/projects/templates/projects/create_user.html:3
+#: dashboards/admin/projects/templates/projects/create_user.html:6
+msgid "Add New User"
+msgstr "Adicionar Novo Usuário"
+
+#: dashboards/admin/projects/templates/projects/usage.html:3
+msgid "Project Usage Overview"
+msgstr "Resumo de Utilização do Projeto"
+
+#: dashboards/admin/projects/templates/projects/usage.html:7
+msgid "Project Usage"
+msgstr "Utilização do Projeto"
+
+#: dashboards/admin/projects/templates/projects/users.html:7
+msgid "Users for Project"
+msgstr "Usuários para o Projeto"
+
+#: dashboards/admin/quotas/panel.py:29 dashboards/admin/quotas/tables.py:36
+msgid "Quotas"
+msgstr "Quotas"
+
+#: dashboards/admin/quotas/tables.py:28
+msgid "Quota Name"
+msgstr "Nome de Quota"
+
+#: dashboards/admin/quotas/tables.py:29
+msgid "Limit"
+msgstr "Limite"
+
+#: dashboards/admin/quotas/views.py:46
+msgid "Unable to get quota info."
+msgstr "Não foi possível obter informações de quota"
+
+#: dashboards/admin/quotas/templates/quotas/index.html:8
+msgid "Default Quotas"
+msgstr "Quotas Padrão"
+
+#: dashboards/admin/services/panel.py:29
+#: dashboards/admin/services/tables.py:47
+#: dashboards/admin/services/templates/services/index.html:8
+msgid "Services"
+msgstr "Serviços"
+
+#: dashboards/admin/services/tables.py:37
+msgid "Id"
+msgstr "Id"
+
+#: dashboards/admin/services/tables.py:39
+msgid "Service"
+msgstr "Serviço"
+
+#: dashboards/admin/users/forms.py:54
+msgid "Passwords do not match."
+msgstr "As senhas não combinam."
+
+#: dashboards/admin/users/forms.py:62 dashboards/admin/users/forms.py:115
+#: dashboards/admin/users/tables.py:108
+msgid "User Name"
+msgstr "Nome do Usuário"
+
+#: dashboards/admin/users/forms.py:63 dashboards/admin/users/forms.py:116
+#: dashboards/admin/users/tables.py:109
+msgid "Email"
+msgstr "Email"
+
+#: dashboards/admin/users/forms.py:65 dashboards/admin/users/forms.py:117
+msgid "Password"
+msgstr "Senha"
+
+#: dashboards/admin/users/forms.py:70 dashboards/admin/users/forms.py:124
+msgid "Confirm Password"
+msgstr "Confirme a Senha"
+
+#: dashboards/admin/users/forms.py:73 dashboards/admin/users/forms.py:127
+msgid "Primary Project"
+msgstr "Projeto Primário"
+
+#: dashboards/admin/users/forms.py:75
+msgid "Role"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:96
+#, python-format
+msgid "User \"%s\" was successfully created."
+msgstr "Usuário \"%s\" criado com sucesso."
+
+#: dashboards/admin/users/forms.py:106
+msgid "Unable to add userto primary project."
+msgstr "Não foi possível adicionar usuário ao projeto primário."
+
+#: dashboards/admin/users/forms.py:110
+msgid "Unable to create user."
+msgstr "Falha ao criar usuário."
+
+#: dashboards/admin/users/forms.py:151
+msgid "name"
+msgstr "nome"
+
+#: dashboards/admin/users/forms.py:151
+msgid "email"
+msgstr "email"
+
+#: dashboards/admin/users/forms.py:160
+msgid "primary project"
+msgstr "projeto primário"
+
+#: dashboards/admin/users/forms.py:173
+#, python-format
+msgid "The user %s has no role defined for"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:181
+msgid "password"
+msgstr "senha"
+
+#: dashboards/admin/users/forms.py:190
+msgid "User has been updated successfully."
+msgstr "O usuário foi atualizado com sucesso."
+
+#: dashboards/admin/users/forms.py:194
+#, python-format
+msgid "Unable to update %(attributes)s for the user."
+msgstr "Não foi possível atualizar %(attributes)s para o usuário."
+
+#: dashboards/admin/users/tables.py:32
+#: dashboards/project/images_and_snapshots/images/tables.py:68
+msgid "Edit"
+msgstr "Editar"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Enable"
+msgstr "Habilitar"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Disable"
+msgstr "Desabilitar"
+
+#: dashboards/admin/users/tables.py:40
+msgid "Disabled"
+msgstr "Desabilitado"
+
+#: dashboards/admin/users/tables.py:63
+msgid "You cannot disable the user you are currently logged in as."
+msgstr "Você não pode desabilitar o usuário que você está logado no momento."
+
+#: dashboards/admin/users/tables.py:114
+msgid "User ID"
+msgstr "ID de Usuário"
+
+#: dashboards/admin/users/views.py:70
+msgid "Unable to update user."
+msgstr "Não foi possível atualizar o usuário."
+
+#: dashboards/admin/users/views.py:104
+msgid "Unable to retrieve user roles."
+msgstr "Não é possível recuperar as funções do usuário."
+
+#: dashboards/admin/users/templates/users/_create.html:17
+msgid "From here you can create a new user and assign them to a project."
+msgstr "Aqui você pode criar um novo usuário e associar ele a um projeto."
+
+#: dashboards/admin/users/templates/users/_update.html:7
+#: dashboards/admin/users/templates/users/_update.html:22
+#: dashboards/admin/users/templates/users/update.html:7
+msgid "Update User"
+msgstr "Atualizar Usuário"
+
+#: dashboards/admin/users/templates/users/_update.html:17
+msgid ""
+"From here you can edit the user's details, including their default project."
+msgstr ""
+"Aqui você pode editar os detalhes de usuário, incluindo o projeto padrão "
+"dele."
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:3
+#: dashboards/project/volumes/templates/volumes/detail.html:3
+msgid "Volume Details"
+msgstr "Detalhes do Volume"
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:6
+#: dashboards/project/volumes/templates/volumes/detail.html:6
+msgid "Volume Detail"
+msgstr "Detalhe do Volume"
+
+#: dashboards/project/dashboard.py:24
+msgid "Manage Compute"
+msgstr "Administrar Computar"
+
+#: dashboards/project/dashboard.py:35
+msgid "Object Store"
+msgstr "Armazenar o Objeto"
+
+#: dashboards/project/access_and_security/panel.py:26
+#: dashboards/project/instances/workflows.py:348
+msgid "Access & Security"
+msgstr "Acesso e Segurança"
+
+#: dashboards/project/access_and_security/views.py:51
+msgid "Unable to retrieve keypair list."
+msgstr "Não foi possível recuperar a lista de par de chaves."
+
+#: dashboards/project/access_and_security/views.py:60
+#: dashboards/project/access_and_security/security_groups/views.py:74
+msgid "Unable to retrieve security groups."
+msgstr "Não é possível recuperar grupos de segurança"
+
+#: dashboards/project/access_and_security/views.py:69
+#: dashboards/project/access_and_security/floating_ips/workflows.py:49
+msgid "Unable to retrieve floating IP addresses."
+msgstr "Não foi possível obter o endereço IP flutuante."
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:32
+msgid "Pool"
+msgstr "Conjunto"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:43
+#, python-format
+msgid "Allocated Floating IP %(ip)s."
+msgstr "Alocados IP Flutuante %(ip)s"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:47
+msgid "Unable to allocate Floating IP."
+msgstr "Incapaz de alocar IP flutuante."
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:37
+msgid "Allocate IP To Project"
+msgstr "Alocar IP para Projeto"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:47
+msgid "Release"
+msgstr "Liberar"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:48
+msgid "Released"
+msgstr "Liberado"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:49
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:22
+msgid "Floating IP"
+msgstr "IP Flutuante"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:6
+#: dashboards/project/instances/tables.py:219
+msgid "Associate Floating IP"
+msgstr "IP Flutuante associado"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:76
+msgid "Disassociate Floating IP"
+msgstr "Remover IP Flutuante"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:90
+#, python-format
+msgid "Successfully disassociated Floating IP: %s"
+msgstr "Com sucesso dissociada IP flutuante: %s"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:94
+msgid "Unable to disassociate floating IP."
+msgstr "Não é possível associar IP flutuante"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:114
+#: dashboards/project/access_and_security/floating_ips/workflows.py:36
+#: dashboards/project/instances/tables.py:69
+#: dashboards/project/instances/tables.py:89
+#: dashboards/project/instances/tables.py:106
+#: dashboards/project/instances/tables.py:135
+#: dashboards/project/volumes/tables.py:206
+msgid "Instance"
+msgstr "Instância"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:117
+msgid "Floating IP Pool"
+msgstr "Conjunto Flutuante IP"
+
+#: dashboards/project/access_and_security/floating_ips/views.py:65
+msgid "Unable to retrieve floating IP pools."
+msgstr "Não é possível recuperar flutuantes conjuntos IP."
+
+#: dashboards/project/access_and_security/floating_ips/views.py:68
+msgid "No floating IP pools available."
+msgstr "Sem flutuantes conjuntos IP disponível."
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:40
+msgid "Select the IP address you wish to associate with the selected instance."
+msgstr ""
+"Escolha o endereço IP que você deseja associar com a instância selecionada."
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:53
+msgid "Select an IP address"
+msgstr "Selecione um endereço IP"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:55
+msgid "No IP addresses available"
+msgstr "Nenhum endereço IP disponível"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:76
+#: dashboards/project/volumes/forms.py:160
+msgid "Select an instance"
+msgstr "Selecione um ID"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:78
+#: dashboards/project/volumes/forms.py:162
+msgid "No instances available"
+msgstr "Não há instâncias disponíveis"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:97
+msgid "Manage Floating IP Associations"
+msgstr "Gerenciar Associações de IP Flutuante"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:98
+msgid "Associate"
+msgstr "Associar"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:99
+#, python-format
+msgid "IP address %s associated."
+msgstr "Endereço IP %s associado."
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:100
+#, python-format
+msgid "Unable to associate IP address %s."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:38
+#: dashboards/project/access_and_security/keypairs/forms.py:49
+#: dashboards/project/access_and_security/keypairs/tables.py:52
+msgid "Keypair Name"
+msgstr "Par de Chaves Nome"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:40
+msgid ""
+"Keypair names may only contain letters, numbers, underscores and hyphens."
+msgstr ""
+"Nomes par de chaves pode conter apenas letras, números, sublinhados e hífens."
+
+#: dashboards/project/access_and_security/keypairs/forms.py:51
+msgid "Public Key"
+msgstr "Chave Pública"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:60
+#, python-format
+msgid "Successfully imported public key: %s"
+msgstr "Importado com sucesso chave pública: %s"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:65
+msgid "Unable to import keypair."
+msgstr "Não foi possível importar o par de chave."
+
+#: dashboards/project/access_and_security/keypairs/tables.py:30
+#: dashboards/project/instances/tables.py:295
+#: dashboards/project/instances/workflows.py:335
+msgid "Keypair"
+msgstr "Par de chave"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:31
+#: dashboards/project/access_and_security/keypairs/tables.py:60
+msgid "Keypairs"
+msgstr "Par de chaves"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:39
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html:6
+msgid "Import Keypair"
+msgstr "Importar Par de Chaves"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:46
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html:6
+msgid "Create Keypair"
+msgstr "Criar Par de Chaves"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:53
+msgid "Fingerprint"
+msgstr "Impressão Digital"
+
+#: dashboards/project/access_and_security/keypairs/views.py:74
+#, python-format
+msgid "Unable to create keypair: %(exc)s"
+msgstr "Não é possível criar par de chaves: %(exc)s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:46
+#, python-format
+msgid "Successfully created security group: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:52
+msgid "Unable to create security group."
+msgstr "Não é possível criar grupo de segurança."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:57
+#: dashboards/project/access_and_security/security_groups/tables.py:93
+msgid "IP Protocol"
+msgstr "Protocolo IP"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:61
+msgid "The protocol which this rule should be applied to."
+msgstr "O protocolo que essa regra deve ser aplicada."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:65
+#: dashboards/project/access_and_security/security_groups/forms.py:71
+#: dashboards/project/access_and_security/security_groups/tables.py:95
+msgid "From Port"
+msgstr "A partir da porta"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:66
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP type in the range (-1: 255)"
+msgstr ""
+"TCP / UDP: Digite o valor inteiro entre 1 e 65535. ICMP: insira um valor "
+"para ICMP tipo no intervalo (-1: 255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:72
+#: dashboards/project/images_and_snapshots/images/tables.py:115
+msgid "Type"
+msgstr "Tipo"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:74
+#: dashboards/project/access_and_security/security_groups/forms.py:80
+#: dashboards/project/access_and_security/security_groups/tables.py:96
+msgid "To Port"
+msgstr "Para portar"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:75
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP code in the range (-1: 255)"
+msgstr ""
+"TCP / UDP: Digite o valor inteiro entre 1 e 65535. ICMP: insira um valor "
+"para o código ICMP no intervalo (-1: 255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:81
+msgid "Code"
+msgstr "Código"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:84
+msgid "Source Group"
+msgstr "Grupo de Fonte"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:86
+msgid ""
+"To specify an allowed IP range, select CIDR. To allow access from all "
+"members of another security group select Source Group."
+msgstr ""
+"Para especificar um intervalo IP permitido, selecione CIDR. Para permitir o "
+"acesso de todos os membros de um outro grupo de segurança fonte seleto grupo."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:94
+msgid "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+msgstr "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:121
+msgid "The ICMP type is invalid."
+msgstr "O tipo ICMP é inválido."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:124
+msgid "The ICMP code is invalid."
+msgstr "O código ICMP é inválido."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:127
+msgid "The ICMP type not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:130
+msgid "The ICMP code not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:134
+msgid "The \"from\" port number is invalid."
+msgstr "O número de porta \"de\" é inválido."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:137
+msgid "The \"to\" port number is invalid."
+msgstr "O número de porta \"a\" é inválido."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:140
+msgid ""
+"The \"to\" port number must be greater than or equal to the \"from\" port "
+"number."
+msgstr ""
+"O número de porta \"a\" tem de ser maior do que ou igual ao número de porta "
+"\"de\"."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:146
+msgid "Either CIDR or Source Group may be specified, but not both."
+msgstr "CIDR ou Grupo de Fonte pode ser especificado, mas não ambos."
+
+#: dashboards/project/access_and_security/security_groups/forms.py:168
+#, python-format
+msgid "Successfully added rule: %s"
+msgstr "Regra adicionado com sucesso: %s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:173
+msgid "Unable to add rule to security group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:31
+msgid "Security Group"
+msgstr "Grupo de Segurança"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:32
+#: dashboards/project/access_and_security/security_groups/tables.py:66
+#: dashboards/project/instances/workflows.py:340
+#: dashboards/project/instances/templates/instances/_detail_overview.html:49
+msgid "Security Groups"
+msgstr "Grupos de Segurança"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:45
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html:6
+msgid "Create Security Group"
+msgstr "Criar Grupo de Segurança"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:52
+msgid "Edit Rules"
+msgstr "Editar Regrars"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:72
+msgid "Rule"
+msgstr "Regra"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:73
+msgid "Rules"
+msgstr "Regras"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:97
+msgid "Source"
+msgstr "Fonte"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:107
+msgid "Security Group Rules"
+msgstr "Regras de Segurança do Grupo"
+
+#: dashboards/project/access_and_security/security_groups/views.py:60
+msgid "Unable to retrieve security group."
+msgstr "Não é possível recuperar grupo de segurança"
+
+#: dashboards/project/access_and_security/security_groups/views.py:80
+#, python-format
+msgid "%s (current)"
+msgstr "%s (atual)"
+
+#: dashboards/project/access_and_security/templates/access_and_security/index.html:6
+msgid "Access &amp; Security"
+msgstr "Acesso &amp; Segurança"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:8
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html:3
+msgid "Allocate Floating IP"
+msgstr "Alocar IP Flutuante"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:18
+msgid "Allocate a floating IP from a given floating ip pool."
+msgstr "Alocar um IP flutuante a partir de um determinado pool de IP"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:20
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:19
+msgid "Project Quotas"
+msgstr "Quotas de Projeto"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:31
+msgid "Allocate IP"
+msgstr "Alocar IP"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:17
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:17
+msgid ""
+"Keypairs are ssh credentials which are injected into images when they are "
+"launched. Creating a new key pair registers the public key and downloads the "
+"private key (a .pem file)."
+msgstr ""
+"Pares de chaves são credenciais ssh que são injetadas em imagens quando elas "
+"são executadas. A criação de um novo par de chaves registra a chave pública "
+"e transfere a chave privada (um arquivo .pem)."
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:18
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:18
+msgid "Protect and use the key as you would any normal ssh private key."
+msgstr ""
+"Proteger e usar as chaves como faria normalmente com qualquer chave SSH "
+"privada. "
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:6
+msgid "Download Keypair"
+msgstr "Download par de chaves"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:11
+#, python-format
+msgid ""
+"The keypair &quot;%(keypair_name)s&quot; should download automatically. If "
+"not use the link below."
+msgstr ""
+"O par-de-chaves &quot;%(keypair_name)s&quot; deve ser baixado "
+"automaticamente, caso não seja, utilize o link abaixo."
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:15
+#, python-format
+msgid "Download keypair &quot;%(keypair_name)s&quot;"
+msgstr "Baixe o par-de-chaves &quot;%(keypair_name)s&quot;"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:18
+msgid "From here you can create a new security group"
+msgstr "A partir daqui você pode criar um novo grupo de segurança"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:9
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html:6
+msgid "Edit Security Group Rules"
+msgstr "Editar regras do Grupo de Segurança "
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:12
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:19
+msgid "Add Rule"
+msgstr "Adicionar Regra"
+
+#: dashboards/project/containers/browsers.py:26
+msgid "Swift"
+msgstr "Swift"
+
+#: dashboards/project/containers/browsers.py:29
+#: dashboards/project/containers/tables.py:40
+msgid "Container"
+msgstr "Recipiente"
+
+#: dashboards/project/containers/forms.py:39
+msgid "Slash is not an allowed character."
+msgstr "Barra não é um caracter permitido."
+
+#: dashboards/project/containers/forms.py:49
+#: dashboards/project/containers/tables.py:121
+msgid "Container Name"
+msgstr "Nome do Recipiente"
+
+#: dashboards/project/containers/forms.py:57
+msgid "Container created successfully."
+msgstr "Recipiente criado com sucesso"
+
+#: dashboards/project/containers/forms.py:68
+msgid "Folder created successfully."
+msgstr "Pasta criada com sucesso."
+
+#: dashboards/project/containers/forms.py:71
+msgid "Unable to create container."
+msgstr "Não é possível criar recipiente"
+
+#: dashboards/project/containers/forms.py:79
+#: dashboards/project/containers/tables.py:253
+msgid "Object Name"
+msgstr "Nome do Objeto"
+
+#: dashboards/project/containers/forms.py:81
+msgid "File"
+msgstr "Arquivo"
+
+#: dashboards/project/containers/forms.py:95
+msgid "Object was successfully uploaded."
+msgstr "Objeto foi carregado com sucesso."
+
+#: dashboards/project/containers/forms.py:98
+msgid "Unable to upload object."
+msgstr "Não é possível carregar objeto"
+
+#: dashboards/project/containers/forms.py:102
+msgid "Destination container"
+msgstr "Recipiente de destino"
+
+#: dashboards/project/containers/forms.py:106
+msgid "Destination object name"
+msgstr "Nome do objeto de destino"
+
+#: dashboards/project/containers/forms.py:137
+#: dashboards/project/containers/forms.py:163
+msgid "Unable to copy object."
+msgstr "Não é possível copiar objetos"
+
+#: dashboards/project/containers/forms.py:153
+#, python-format
+msgid "Copied \"%(orig)s\" to \"%(dest)s\" as \"%(new)s\"."
+msgstr ""
+
+#: dashboards/project/containers/panel.py:29
+#: dashboards/project/containers/tables.py:41
+#: dashboards/project/containers/tables.py:128
+#: dashboards/project/containers/templates/containers/index.html:7
+msgid "Containers"
+msgstr "Recipientes"
+
+#: dashboards/project/containers/tables.py:62
+#: dashboards/project/containers/templates/containers/_create.html:7
+#: dashboards/project/containers/templates/containers/_create.html:22
+#: dashboards/project/containers/templates/containers/create.html:6
+msgid "Create Container"
+msgstr "Criar Recipiente"
+
+#: dashboards/project/containers/tables.py:69
+msgid "View Container"
+msgstr "Visualizar Container"
+
+#: dashboards/project/containers/tables.py:81
+#: dashboards/project/containers/templates/containers/_upload.html:23
+#: dashboards/project/containers/templates/containers/upload.html:3
+msgid "Upload Object"
+msgstr "Carregar Objetos"
+
+#: dashboards/project/containers/tables.py:137
+#: dashboards/project/containers/tables.py:156
+msgid "Object"
+msgstr "Objeto"
+
+#: dashboards/project/containers/tables.py:138
+#: dashboards/project/containers/tables.py:157
+#: dashboards/project/containers/tables.py:263
+msgid "Objects"
+msgstr "Objectos"
+
+#: dashboards/project/containers/tables.py:149
+msgid "Folder"
+msgstr "Pasta"
+
+#: dashboards/project/containers/tables.py:150
+msgid "Folders"
+msgstr "Pastas"
+
+#: dashboards/project/containers/tables.py:163
+msgid "Copy"
+msgstr "Copiar"
+
+#: dashboards/project/containers/tables.py:176
+msgid "Download"
+msgstr "Baixar"
+
+#: dashboards/project/containers/tables.py:232
+msgid "Create Folder"
+msgstr "Criar Pasta"
+
+#: dashboards/project/containers/views.py:53
+msgid "Unable to retrieve container list."
+msgstr "Não foi possível recuperar a lista de recipiente."
+
+#: dashboards/project/containers/views.py:82
+msgid "Unable to retrieve object list."
+msgstr "Não foi possível recuperar a lista de objeto."
+
+#: dashboards/project/containers/views.py:166
+msgid "Unable to retrieve object."
+msgstr "Não foi possível recuperar o objeto."
+
+#: dashboards/project/containers/views.py:200
+msgid "Unable to list containers."
+msgstr "Impossível listar recipientes."
+
+#: dashboards/project/containers/templates/containers/_copy.html:7
+#: dashboards/project/containers/templates/containers/_copy.html:22
+#: dashboards/project/containers/templates/containers/copy.html:3
+#: dashboards/project/containers/templates/containers/copy.html:6
+msgid "Copy Object"
+msgstr "Copiar Objeto"
+
+#: dashboards/project/containers/templates/containers/_copy.html:17
+msgid ""
+"Make a new copy of an existing object to store in this or another container. "
+"You may also specify a path at which the new copy should live inside of the "
+"selected container."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_create.html:17
+msgid ""
+"A container is a storage compartment for your data and provides a way for "
+"you to organize your data. You can think of a container as a folder in "
+"Windows &reg; or a directory in UNIX &reg;. The primary difference between a "
+"container and these other file system concepts is that containers cannot be "
+"nested. You can, however, create an unlimited number of containers within "
+"your account. Data must be stored in a container so you must have at least "
+"one container defined in your account prior to uploading data."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:8
+msgid "Upload Object To Container"
+msgstr "Enviar objeto para o Container."
+
+#: dashboards/project/containers/templates/containers/_upload.html:18
+msgid ""
+"An object is the basic storage entity and any optional metadata that "
+"represents the files you store in the OpenStack Object Storage system. When "
+"you upload data to OpenStack Object Storage, the data is stored as-is (no "
+"compression or encryption) and consists of a location (container), the "
+"object's name, and any metadata consisting of key/value pairs."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/upload.html:6
+msgid "Upload Objects"
+msgstr "Enviar Objetos"
+
+#: dashboards/project/images_and_snapshots/panel.py:26
+msgid "Images & Snapshots"
+msgstr "Imagens e Instantâneos"
+
+#: dashboards/project/images_and_snapshots/views.py:63
+msgid "Unable to retrieve images."
+msgstr "Não é possível recuperar imagens."
+
+#: dashboards/project/images_and_snapshots/views.py:74
+msgid "Unable to retrieve snapshots."
+msgstr "Não é possível recuperar instantâneos."
+
+#: dashboards/project/images_and_snapshots/views.py:82
+#: dashboards/project/volumes/forms.py:65
+msgid "Unable to retrieve volume snapshots."
+msgstr "Não é possível recuperar instantâneos de volume."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:42
+msgid "Image Location"
+msgstr "Local da Imagem"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:43
+msgid "An external (HTTP) URL to load the image from."
+msgstr "Um URL (HTTP) externo para carregar a imagem."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:46
+#: dashboards/project/images_and_snapshots/images/forms.py:130
+#: dashboards/project/images_and_snapshots/images/tables.py:126
+msgid "Format"
+msgstr "Formato"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:50
+msgid "AKI - Amazon Kernel Image"
+msgstr "AKI - Imagem de Kernel da Amazon"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:53
+msgid "AMI - Amazon Machine Image"
+msgstr "AMI - Imagem de máquina Amazon"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:56
+msgid "ARI - Amazon Ramdisk Image"
+msgstr "ARI - Imagem de Ramdisk Amazon"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:59
+msgid "ISO - Optical Disk Image"
+msgstr "ISO - Imagem de disco óptico"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:61
+msgid "QCOW2 - QEMU Emulator"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:68
+msgid "Minimum Disk (GB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:69
+#: dashboards/project/images_and_snapshots/images/forms.py:76
+msgid ""
+"The minimum disk size required to boot the image. If unspecified, this value "
+"defaults to 0 (no minimum)."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:75
+msgid "Minimum Ram (MB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:82
+#: dashboards/project/images_and_snapshots/images/forms.py:134
+#: dashboards/project/images_and_snapshots/images/tables.py:123
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:15
+msgid "Public"
+msgstr "Público"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:106
+#, python-format
+msgid "Your image %s has been queued for creation."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:110
+msgid "Unable to create new image."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:116
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:48
+msgid "Kernel ID"
+msgstr "Kernel ID"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:121
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:52
+msgid "Ramdisk ID"
+msgstr "Ramdisk ID"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:126
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:44
+msgid "Architecture"
+msgstr "Arquitetura"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:138
+#, python-format
+msgid "Unable to update image \"%s\"."
+msgstr "Não é possível atualizar imagem \"%s\"."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:162
+msgid "Image was successfully updated."
+msgstr "A imagem foi atualizado com sucesso."
+
+#: dashboards/project/images_and_snapshots/images/tables.py:34
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:33
+#: dashboards/project/instances/workflows.py:455
+msgid "Launch"
+msgstr "Lançar"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:46
+#: dashboards/project/images_and_snapshots/images/tables.py:82
+#: dashboards/project/instances/workflows.py:168
+#: dashboards/project/instances/workflows.py:173
+msgid "Image"
+msgstr "Imagem"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:61
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:31
+msgid "Create Image"
+msgstr "Criar Imagem"
+
+#: dashboards/project/images_and_snapshots/images/tabs.py:38
+msgid "Unable to retrieve image details."
+msgstr "Não foi possível obter detalhes da imagem."
+
+#: dashboards/project/images_and_snapshots/images/views.py:61
+msgid "Unable to retrieve image."
+msgstr "Não foi possível obter a imagem"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:37
+msgid "Instance ID"
+msgstr "ID instância"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:40
+#: dashboards/project/volumes/forms.py:193
+msgid "Snapshot Name"
+msgstr "Nome de Instantâneo"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:50
+#, python-format
+msgid "Snapshot \"%(name)s\" created for instance \"%(inst)s\""
+msgstr "instantâneo \"%(name)s\" criou, por instâneo \"%(inst)s\""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:56
+msgid "Unable to create snapshot."
+msgstr "Não é possível criar instantâneo."
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:48
+#: dashboards/project/instances/workflows.py:107
+#: dashboards/project/instances/workflows.py:169
+msgid "Snapshot"
+msgstr "Instantâneo"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:49
+msgid "Snapshots"
+msgstr "Instantâneos"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:55
+msgid "Instance Snapshots"
+msgstr "Instantâneos de Instâncias"
+
+#: dashboards/project/images_and_snapshots/snapshots/views.py:53
+msgid "Unable to retrieve instance."
+msgstr "Incapaz de recuperar instância."
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:6
+msgid "Images &amp; Snapshots"
+msgstr "Images &amp; Snapshots"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:6
+msgid "Create An Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:18
+msgid "Specify an image to upload to the Image Service."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:21
+msgid ""
+"Currently only images available via an HTTP URL are supported. The image "
+"location must be accessible to the Image Service. Compressed image binaries "
+"are supported (.zip and .tar.gz.)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:24
+msgid "Please note: "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:25
+msgid ""
+"The Image Location field MUST be a valid and direct URL to the image binary. "
+"URLs that redirect or serve error pages will result in unusable images."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:3
+msgid "Image Overview"
+msgstr "Visão geral da Imagem"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:6
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:7
+#: dashboards/project/instances/templates/instances/_detail_overview.html:6
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:6
+msgid "Info"
+msgstr "Informações"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:17
+msgid "Checksum"
+msgstr "Checksum"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:19
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:39
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:28
+msgid "Created"
+msgstr "Criado"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:21
+msgid "Updated"
+msgstr "Atualizado"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:27
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:34
+#: dashboards/project/instances/templates/instances/_detail_overview.html:19
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:23
+msgid "Specs"
+msgstr "Especificações"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:32
+msgid "Container Format"
+msgstr "Formato do Recipiente"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:34
+msgid "Disk Format"
+msgstr "Formato do Disco"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:40
+msgid "Custom Properties"
+msgstr "Propriedades personalizadas"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:56
+msgid "Euca2ools state"
+msgstr "Estado Euca2ools"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:64
+msgid "Image Type"
+msgstr "Tipo de imagem"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html:4
+msgid "Image Detail "
+msgstr "Detalhes da Imagem"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:8
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:3
+#: dashboards/project/instances/tables.py:179
+#: dashboards/project/volumes/tables.py:76
+msgid "Create Snapshot"
+msgstr "Criar Snapshot"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:18
+msgid "Snapshots preserve the disk state of a running instance."
+msgstr "Snapshots preservam o estado do disco de uma instância em execução."
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:20
+#: dashboards/project/instances/workflows.py:75
+#: dashboards/project/instances/workflows.py:110
+#: dashboards/project/instances/templates/instances/_detail_overview.html:93
+#: dashboards/project/volumes/tables.py:37
+#: dashboards/project/volumes/tables.py:182
+msgid "Volume"
+msgstr "Volume"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:38
+#: dashboards/project/instances/templates/instances/_detail_overview.html:29
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:27
+msgid "GB"
+msgstr "GB"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:6
+msgid "Create a Snapshot"
+msgstr "Criar um Snapshot"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:3
+#, fuzzy
+msgid "Volume Snapshot Details"
+msgstr "Volume Instantâneos"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:6
+#, fuzzy
+msgid "Volume Snapshot Detail"
+msgstr "Volume Instantâneo"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:34
+#: dashboards/project/instances/workflows.py:76
+msgid "Volume Snapshot"
+msgstr "Volume Instantâneo"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:35
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:85
+msgid "Volume Snapshots"
+msgstr "Volume Instantâneos"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:43
+#: dashboards/project/volumes/tables.py:59
+#: dashboards/project/volumes/templates/volumes/_create.html:8
+#: dashboards/project/volumes/templates/volumes/_create.html:55
+msgid "Create Volume"
+msgstr "Criar Volume"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:80
+#: dashboards/project/volumes/forms.py:26
+msgid "Volume Name"
+msgstr "Nome do Volume"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:41
+#, fuzzy
+msgid "Unable to retrieve snapshot details."
+msgstr "Não é possível recuperar instantâneos."
+
+#: dashboards/project/instances/forms.py:45
+#, python-format
+msgid "Instance \"%s\" updated."
+msgstr "Instância \"%s\" atualizado."
+
+#: dashboards/project/instances/forms.py:50
+msgid "Unable to update instance."
+msgstr "Não é possível atualizar instância"
+
+#: dashboards/project/instances/tables.py:67
+msgid "Terminate"
+msgstr "Terminar"
+
+#: dashboards/project/instances/tables.py:68
+msgid "Scheduled termination of"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:87
+msgid "Reboot"
+msgstr "Reinicializar"
+
+#: dashboards/project/instances/tables.py:88
+msgid "Rebooted"
+msgstr "Reinicializado"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Pause"
+msgstr "Pausa"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Unpause"
+msgstr "Retomar"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Paused"
+msgstr "Pausada"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Unpaused"
+msgstr "Retomado"
+
+#: dashboards/project/instances/tables.py:133
+msgid "Suspend"
+msgstr "Suspender"
+
+#: dashboards/project/instances/tables.py:133
+msgid "Resume"
+msgstr "Retomar"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Suspended"
+msgstr "Em suspensão"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Resumed"
+msgstr "Retomado"
+
+#: dashboards/project/instances/tables.py:162
+#: dashboards/project/instances/workflows.py:454
+#: dashboards/project/instances/templates/instances/launch.html:3
+#: dashboards/project/instances/templates/instances/launch.html:6
+msgid "Launch Instance"
+msgstr "Lançamento Instância"
+
+#: dashboards/project/instances/tables.py:169
+#: dashboards/project/instances/templates/instances/_update.html:7
+msgid "Edit Instance"
+msgstr "Editar Instância"
+
+#: dashboards/project/instances/tables.py:189
+msgid "VNC Console"
+msgstr "VNC Console"
+
+#: dashboards/project/instances/tables.py:204
+msgid "View Log"
+msgstr "Ver log"
+
+#: dashboards/project/instances/tables.py:252
+#, python-format
+msgid "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disk"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:259
+#: dashboards/project/instances/tables.py:266
+msgid "Not available"
+msgstr "Não disponível"
+
+#: dashboards/project/instances/tabs.py:36
+msgid "Log"
+msgstr "Log"
+
+#: dashboards/project/instances/tabs.py:48
+#: dashboards/project/instances/views.py:106
+#, python-format
+msgid "Unable to get log for instance \"%s\"."
+msgstr "Não foi possível obter o log da instância \"%s\"."
+
+#: dashboards/project/instances/tabs.py:55
+msgid "VNC"
+msgstr "VNC"
+
+#: dashboards/project/instances/tabs.py:70
+#: dashboards/project/instances/views.py:122
+#, python-format
+msgid "Unable to get VNC console for instance \"%s\"."
+msgstr "Não foi possível acessar o console VNC da instância \"%s\"."
+
+#: dashboards/project/instances/views.py:59
+msgid "Unable to retrieve instances."
+msgstr "Incapaz de recuperar instâncias."
+
+#: dashboards/project/instances/views.py:144
+msgid "Unable to retrieve instance details."
+msgstr "Não foi possível recuperar os detalhes da instância."
+
+#: dashboards/project/instances/views.py:179
+#, python-format
+msgid "Unable to retrieve details for instance \"%s\"."
+msgstr "Não foi possível recuperar os detalhes da instância \"%s\"."
+
+#: dashboards/project/instances/workflows.py:53
+msgid "Project & User"
+msgstr "Projeto & Usuário"
+
+#: dashboards/project/instances/workflows.py:66
+msgid "Don't boot from a volume."
+msgstr "Não faça o boot a partir de um volume."
+
+#: dashboards/project/instances/workflows.py:67
+msgid "Boot from volume."
+msgstr "Boot a partir de um volume."
+
+#: dashboards/project/instances/workflows.py:68
+msgid "Boot from volume snapshot (creates a new volume)."
+msgstr "Boot a partir de um snapshot de volume (cria um novo volume)."
+
+#: dashboards/project/instances/workflows.py:72
+#: dashboards/project/instances/workflows.py:90
+msgid "Volume Options"
+msgstr "Opções do Volume"
+
+#: dashboards/project/instances/workflows.py:78
+#: dashboards/project/volumes/forms.py:126
+msgid "Device Name"
+msgstr "Nome do Dispositivo"
+
+#: dashboards/project/instances/workflows.py:81
+msgid "Volume mount point (e.g. 'vda' mounts at '/dev/vda')."
+msgstr ""
+"Volume ponto de montagem (por exemplo: montagens \"vda\" em '/dev/vda')."
+
+#: dashboards/project/instances/workflows.py:83
+msgid "Delete on Terminate"
+msgstr "Excluir em Terminar"
+
+#: dashboards/project/instances/workflows.py:86
+msgid "Delete volume on instance terminate"
+msgstr "Apagar volume na instância terminar."
+
+#: dashboards/project/instances/workflows.py:100
+#, python-format
+msgid "Please choose a volume, or select %s."
+msgstr "Por favor selecione um volume, ou selecione %s."
+
+#: dashboards/project/instances/workflows.py:117
+msgid "Select Volume"
+msgstr "Selecione Volume"
+
+#: dashboards/project/instances/workflows.py:125
+msgid "Unable to retrieve list of volumes."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:129
+msgid "Select Volume Snapshot"
+msgstr "Selecionar Snapshot do Volume"
+
+#: dashboards/project/instances/workflows.py:138
+msgid "Unable to retrieve list of volume snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:171
+msgid "Instance Source"
+msgstr "Origem da Instância"
+
+#: dashboards/project/instances/workflows.py:174
+msgid "Instance Snapshot"
+msgstr "Snapshot da Instância"
+
+#: dashboards/project/instances/workflows.py:178
+msgid "Size of image to launch."
+msgstr "Tamanho de imagem para iniciar"
+
+#: dashboards/project/instances/workflows.py:179
+msgid "Instance Count"
+msgstr "Contagem de Instância"
+
+#: dashboards/project/instances/workflows.py:182
+msgid "Number of instances to launch."
+msgstr "Número de instâncias de lançamento"
+
+#: dashboards/project/instances/workflows.py:185
+msgid "Details"
+msgstr "Detalhes"
+
+#: dashboards/project/instances/workflows.py:198
+msgid ""
+"There are no image sources available; you must first create an image before "
+"attempting to launch an instance."
+msgstr ""
+"Não existem fontes de imagem disponíveis. Primeiro você deve criar uma "
+"imagem antes de tentar iniciar uma instância."
+
+#: dashboards/project/instances/workflows.py:203
+msgid "Please select an option for the instance source."
+msgstr "Selecione uma opção para a fonte de instância."
+
+#: dashboards/project/instances/workflows.py:212
+msgid ""
+"Launching multiple instances is only supported for images and instance "
+"snapshots."
+msgstr ""
+"Executar múltiplas instâncias é suportado apenas para imagens e snapshots de "
+"instâncias."
+
+#: dashboards/project/instances/workflows.py:229
+msgid "Unable to retrieve public images."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:244
+msgid "Unable to retrieve images for the current project."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:267
+msgid "Select Image"
+msgstr "Selecionar Imagem"
+
+#: dashboards/project/instances/workflows.py:269
+msgid "No images available."
+msgstr "Nenhuma imagem disponível."
+
+#: dashboards/project/instances/workflows.py:278
+msgid "Select Instance Snapshot"
+msgstr "Selecionar Snapshot da Instância"
+
+#: dashboards/project/instances/workflows.py:280
+msgid "No snapshots available."
+msgstr "Não existem snapshots disponíveis."
+
+#: dashboards/project/instances/workflows.py:291
+msgid "Unable to retrieve instance flavors."
+msgstr "Não foi possível recuperar os sabores de instância."
+
+#: dashboards/project/instances/workflows.py:304 usage/base.py:114
+msgid "Unable to retrieve quota information."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:337
+msgid "Which keypair to use for authentication."
+msgstr "Que par de chaves para autenticação."
+
+#: dashboards/project/instances/workflows.py:344
+msgid "Launch instance in these security groups."
+msgstr "Lançar instância em esses grupos de segurança."
+
+#: dashboards/project/instances/workflows.py:349
+msgid ""
+"Control access to your instance via keypairs, security groups, and other "
+"mechanisms."
+msgstr ""
+"Controle o acesso para sua instância a partir do par de chaves, grupos de "
+"segurança e outros mecanismos."
+
+#: dashboards/project/instances/workflows.py:359
+msgid "Unable to retrieve keypairs."
+msgstr "Não é possível recuperar pares de chaves."
+
+#: dashboards/project/instances/workflows.py:361
+msgid "Select a keypair"
+msgstr "Selecionar um par de chaves"
+
+#: dashboards/project/instances/workflows.py:363
+msgid "No keypairs available."
+msgstr "Não pares de chaves disponíveis."
+
+#: dashboards/project/instances/workflows.py:372
+msgid "Unable to retrieve list of security groups"
+msgstr "Não é possível recuperar a lista de grupos de segurança"
+
+#: dashboards/project/instances/workflows.py:392
+msgid "Customization Script"
+msgstr "Script de Customização"
+
+#: dashboards/project/instances/workflows.py:394
+msgid ""
+"A script or set of commands to be executed after the instance has been built "
+"(max 16kb)."
+msgstr ""
+"Um script ou conjunto de comandos para serem executados após a instância ser "
+"criada (máximo de 16kb)."
+
+#: dashboards/project/instances/workflows.py:401
+msgid "Post-Creation"
+msgstr "Após-Criação"
+
+#: dashboards/project/instances/workflows.py:415
+msgid "Launch instance withthese networks"
+msgstr "Lançar instância com estas redes."
+
+#: dashboards/project/instances/workflows.py:419
+msgid "Networking"
+msgstr "Rede"
+
+#: dashboards/project/instances/workflows.py:421
+msgid "Select networks for your instance."
+msgstr "Selecione as redes para sua instância."
+
+#: dashboards/project/instances/workflows.py:433
+msgid "Unable to retrieve networks."
+msgstr "Não é possível recuperar redes."
+
+#: dashboards/project/instances/workflows.py:456
+#, python-format
+msgid "Launched %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:457
+#, python-format
+msgid "Unable to launch %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:470
+#, python-format
+msgid "%s instances"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:473
+msgid "instance"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:4
+msgid "Instance Console Log"
+msgstr "Log Console Instância"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:7
+msgid "Log Length"
+msgstr "Log Tamanho"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:9
+msgid "Go"
+msgstr "Vai"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:11
+msgid "View Full Log"
+msgstr "Visualizar log completo"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:3
+msgid "Instance Overview"
+msgstr "Visão geral da instância"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:27
+msgid "VCPU"
+msgstr "VCPU"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:28
+#: usage/tables.py:20
+msgid "Disk"
+msgstr "Disco"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:34
+msgid "IP Addresses"
+msgstr "Endereço IP"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:59
+msgid "No rules defined."
+msgstr "Nenhuma regra definida."
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:68
+msgid "Meta"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:71
+msgid "Key Name"
+msgstr "Nome da chave"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:84
+msgid "Volumes Attached"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:88
+#: dashboards/project/volumes/tables.py:167
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:38
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:45
+msgid "Attached To"
+msgstr "Conectado com"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:90
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:42
+msgid "on"
+msgstr "ligado"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:94
+msgid "No volumes attached."
+msgstr "Nenhum volume anexado."
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:3
+msgid "Instance VNC Console"
+msgstr "Console VNC da instância"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid ""
+"If VNC console is not responding to keyboard input: click the grey status "
+"bar below."
+msgstr ""
+"Caso o console VNC não esteja respondendo a entrada do teclado, clique na "
+"barra de status cinza abaixo."
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid "Click here to show only VNC"
+msgstr "Clique aqu para mostrar somente o VNC"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:8
+msgid "VNC console is currently unavailabe. Please try again later."
+msgstr ""
+"Console VNC está indisponível no momento, Por favor tente novamente depois."
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:9
+msgid "Reload"
+msgstr "Recarregar"
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:2
+msgid ""
+"You can customize your instance after it's launched using the options "
+"available here."
+msgstr ""
+"Você pode customizar sua instância após ela ser executada utilizando as "
+"opções disponíveis aqui."
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:3
+msgid ""
+"The \"Customization Script\" field is analogous to \"User Data\" in other "
+"systems."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:3
+msgid "Specify the details for launching an instance."
+msgstr "Especifique os detalhes para a execução de uma instância"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:4
+msgid ""
+"The chart below shows the resources used by this project in relation to the "
+"project's quotas."
+msgstr ""
+"O gráfico abaixo mostra os recursos usados por este projeto em relação as "
+"quotas do projeto."
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:6
+msgid "Flavor Details"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+msgid "Total Disk"
+msgstr "Total de Disco"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "MB"
+msgstr "MB"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:21
+msgid "Number of Instances"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:29
+msgid "Number of VCPUs"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+#, fuzzy
+msgid "Total RAM"
+msgstr "Total de Disco"
+
+#: dashboards/project/instances/templates/instances/_launch_volumes_help.html:3
+msgid ""
+"An instance can be launched with varying types of attached storage. You may "
+"select from those options here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_update.html:17
+msgid "You may update the editable properties of your instance here."
+msgstr "Você pode atualizar as propriedades editáveis da sua instância aqui."
+
+#: dashboards/project/instances/templates/instances/detail.html:3
+msgid "Instance Detail"
+msgstr "Detalhes da Instância"
+
+#: dashboards/project/instances/templates/instances/update.html:3
+#: dashboards/project/instances/templates/instances/update.html:6
+msgid "Update Instance"
+msgstr "Atualizar Instância"
+
+#: dashboards/project/networks/tables.py:81
+msgid "Add Subnet"
+msgstr "Adicionar Sub-rede"
+
+#: dashboards/project/networks/views.py:86
+msgid "Unable to retrieve network details."
+msgstr "Não foi possível obter detalhes da rede."
+
+#: dashboards/project/networks/workflows.py:37
+msgid "Network Name (optional)"
+msgstr "Nome de Rede (opcional)"
+
+#: dashboards/project/networks/workflows.py:42
+msgid ""
+"From here you can create a new network.\n"
+"In addition a subnet associated with the network can be created in the next "
+"panel."
+msgstr ""
+"A partir daí você pode criar uma nova rede. ⏎ Além disso, uma sub-rede "
+"associada com a rede pode ser criado no próximo painel."
+
+#: dashboards/project/networks/workflows.py:56
+msgid "Subnet Name (optional)"
+msgstr "Nome da sub-rede (opcional)"
+
+#: dashboards/project/networks/workflows.py:61
+#: dashboards/project/networks/subnets/forms.py:48
+msgid "Network address in CIDR format (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:67
+msgid "Gateway IP (optional)"
+msgstr "IP do Gateway (opcional)"
+
+#: dashboards/project/networks/workflows.py:70
+#: dashboards/project/networks/subnets/forms.py:57
+#: dashboards/project/networks/subnets/forms.py:107
+msgid "IP address of Gateway (e.g. 192.168.0.1)"
+msgstr "Endereço IP do Gateway (ex.: 192.168.0.1)"
+
+#: dashboards/project/networks/workflows.py:77
+msgid ""
+"You can create a subnet associated with the new network, in which case "
+"\"Network Address\" must be specified. If you wish to create a network "
+"WITHOUT a subnet, uncheck the \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:89
+msgid "Specify \"Network Address\" or clear \"Create Subnet\" checkbox."
+msgstr ""
+"Especifique um \"Endereço de Rede\" ou desmarque a opção \"Criar Subrede\""
+
+#: dashboards/project/networks/workflows.py:94
+#: dashboards/project/networks/subnets/forms.py:70
+msgid "Network Address and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:98
+#: dashboards/project/networks/subnets/forms.py:74
+#: dashboards/project/networks/subnets/forms.py:119
+msgid "Gateway IP and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:112
+msgid "Create"
+msgstr "Criar"
+
+#: dashboards/project/networks/workflows.py:113
+#, python-format
+msgid "Created network \"%s\"."
+msgstr "Rede \"%s\" criada."
+
+#: dashboards/project/networks/workflows.py:114
+#, python-format
+msgid "Unable to create network \"%s\"."
+msgstr "Incapaz de criar a rede \"%s\"."
+
+#: dashboards/project/networks/workflows.py:130
+#, python-format
+msgid "Network \"%s\" was successfully created."
+msgstr "Rede \"%s\" criada com sucesso."
+
+#: dashboards/project/networks/workflows.py:133
+#, python-format
+msgid "Failed to create network \"%s\"."
+msgstr "Falha ao criar rede \"%s\"."
+
+#: dashboards/project/networks/workflows.py:152
+#, python-format
+msgid "Subnet \"%s\" was successfully created."
+msgstr "Sub-rede \"%s\" criada com sucesso."
+
+#: dashboards/project/networks/workflows.py:155
+#, python-format
+msgid "Failed to create subnet \"%(sub)s\" for network \"%(net)s\"."
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Attached"
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Detached"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:85
+#, python-format
+msgid "Subnet %s was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:90
+#, python-format
+msgid "Failed to create subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:131
+#, python-format
+msgid "Subnet %s was successfully updated."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:136
+#, python-format
+msgid "Failed to update subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/tabs.py:42
+msgid "Unable to retrieve subnet details."
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/_detail_overview.html:3
+msgid "Network Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/detail.html:6
+msgid "Network Detail: "
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:3
+msgid "Port Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:17
+msgid "Fixed IP"
+msgstr "IP Fixo"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:21
+msgid "IP address:"
+msgstr "Endereço IP:"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:22
+msgid "Subnet ID"
+msgstr "Identificação da Sub-rede"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:28
+msgid "Mac Address"
+msgstr "Endereço Mac"
+
+#: dashboards/project/networks/templates/networks/ports/detail.html:3
+#: dashboards/project/networks/templates/networks/ports/detail.html:6
+msgid "Port Detail"
+msgstr "Detalhes da Porta"
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:3
+msgid "Subnet Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:21
+msgid "IP allocation pool"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:24
+msgid "Start"
+msgstr "Início"
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:25
+msgid " - End"
+msgstr "- Fim"
+
+#: dashboards/project/networks/templates/networks/subnets/detail.html:3
+#: dashboards/project/networks/templates/networks/subnets/detail.html:6
+msgid "Subnet Detail"
+msgstr "Detalhes da Sub-rede"
+
+#: dashboards/project/volumes/forms.py:29
+msgid "Size (GB)"
+msgstr "Tamanho (GB)"
+
+#: dashboards/project/volumes/forms.py:30
+msgid "Use snapshot as a source"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:49
+#, python-format
+msgid "Volume size must be equal to or greater than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:54
+msgid "Unable to load the specified snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:59
+msgid "Choose a snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:83
+#, python-format
+msgid "The volume size cannot be less than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:92
+#, python-format
+msgid ""
+"A volume of %(req)iGB cannot be created as you only have %(avail)iGB of your "
+"quota available."
+msgstr ""
+"O volume de %(req)iGB não pôde ser criado porque você tem somente "
+"%(avail)iGB de sua quota disponível. "
+
+#: dashboards/project/volumes/forms.py:99
+msgid "You are already using all of your available volumes."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:115
+msgid "Unable to create volume."
+msgstr "Incapaz de criar volume."
+
+#: dashboards/project/volumes/forms.py:123
+msgid "Attach to Instance"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:124
+msgid "Select an instance to attach to."
+msgstr "Selecione uma instância para anexar."
+
+#: dashboards/project/volumes/forms.py:168
+msgid "Unknown instance (None)"
+msgstr "Instância desconhecida (Nenhum)"
+
+#: dashboards/project/volumes/forms.py:179
+#, python-format
+msgid "Attaching volume %(vol)s to instance %(inst)s on %(dev)s."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:188
+msgid "Unable to attach volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:212
+#, python-format
+msgid "Creating volume snapshot \"%s\""
+msgstr "Criando snapshot do volume \"%s\""
+
+#: dashboards/project/volumes/forms.py:218
+msgid "Unable to create volume snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:46
+#, fuzzy, python-format
+msgid "Unable to delete volume \"%s\". One or more snapshots depend on it."
+msgstr "Não é possível recuperar instantâneos de volume."
+
+#: dashboards/project/volumes/tables.py:66
+msgid "Edit Attachments"
+msgstr "Editar Anexos"
+
+#: dashboards/project/volumes/tables.py:93
+#, python-format
+msgid "%sGB"
+msgstr "%s GB"
+
+#: dashboards/project/volumes/tables.py:106
+#: dashboards/project/volumes/views.py:149
+msgid "Unable to retrieve attachment information."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:123
+#, python-format
+msgid "Attached to %(instance)s on %(dev)s"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:180
+msgid "Detach"
+msgstr "Desanexar"
+
+#: dashboards/project/volumes/tables.py:181
+msgid "Detaching"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:216
+#, python-format
+msgid "%(dev)s on instance %(instance_name)s"
+msgstr ""
+
+#: dashboards/project/volumes/tabs.py:42
+msgid "Unable to retrieve volume details."
+msgstr "Não foi possível recuperar detalhes do volume."
+
+#: dashboards/project/volumes/views.py:50
+msgid "Unable to retrieve volume list."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:58
+msgid "Unable to retrieve volume/instance attachment information"
+msgstr ""
+
+#: dashboards/project/volumes/views.py:130
+#: dashboards/project/volumes/views.py:140
+msgid "Unable to retrieve volume information."
+msgstr "Não foi possível recuperar informações do volume."
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:9
+#: dashboards/project/volumes/templates/volumes/attach.html:6
+msgid "Manage Volume Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:13
+msgid "Attach To Instance"
+msgstr "Anexar para uma instância."
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:22
+msgid "Attach Volume"
+msgstr "Anexar volume"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:20
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:18
+msgid "Volumes are block devices that can be attached to instances."
+msgstr ""
+"Volumes são dispositivos de bloco que podem ser conectados com as instâncias."
+
+#: dashboards/project/volumes/templates/volumes/_create.html:22
+msgid "Volume Quotas"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:25
+msgid "Total Gigabytes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:34
+msgid "Number of Volumes"
+msgstr "Número de Volumes"
+
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:8
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:23
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:3
+msgid "Create Volume Snapshot"
+msgstr "Criar Snapshot de um Volume"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:3
+msgid "Volume Overview"
+msgstr "Resumo dos Volumes"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:34
+msgid "Attachments"
+msgstr "Anexos"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:46
+msgid "Not attached"
+msgstr "Não conectado"
+
+#: dashboards/project/volumes/templates/volumes/create.html:6
+msgid "Create a Volume"
+msgstr "Criar um Volume"
+
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:6
+msgid "Create a Volume Snapshot"
+msgstr "Criar Snapshot do Volume"
+
+#: dashboards/settings/dashboard.py:24 templates/_header.html:4
+msgid "Settings"
+msgstr "Configurações"
+
+#: dashboards/settings/ec2/forms.py:36 dashboards/settings/project/forms.py:36
+msgid "Select a Project"
+msgstr "Selecionar um Projeto"
+
+#: dashboards/settings/ec2/forms.py:46
+msgid "Unable to retrieve tenant list."
+msgstr "Não foi possível obter lista de tenant."
+
+#: dashboards/settings/ec2/forms.py:88
+msgid "Unable to fetch EC2 credentials."
+msgstr "Não foi possível obter credenciais EC2."
+
+#: dashboards/settings/ec2/forms.py:101
+#, python-format
+msgid "Error writing zipfile: %(exc)s"
+msgstr "Erro escrevendo arquivo zip: %(exc)s"
+
+#: dashboards/settings/ec2/panel.py:25
+msgid "EC2 Credentials"
+msgstr "Credenciais EC2"
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:8
+#: dashboards/settings/ec2/templates/ec2/download_form.html:23
+#: dashboards/settings/ec2/templates/ec2/index.html:3
+#: dashboards/settings/ec2/templates/ec2/index.html:6
+msgid "Download EC2 Credentials"
+msgstr "Baixar credenciais EC2"
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:18
+msgid ""
+"Clicking \"Download EC2 Credentials\" will download a zip file which "
+"includes an rc file with your access/secret keys, as well as your x509 "
+"private key and certificate."
+msgstr ""
+
+#: dashboards/settings/project/forms.py:71
+#, python-format
+msgid "Error Downloading RC File: %s"
+msgstr "Erro baixando o arquivo RC: %s"
+
+#: dashboards/settings/project/panel.py:25
+#: dashboards/settings/project/templates/project/_openrc.html:8
+#: dashboards/settings/project/templates/project/settings.html:3
+#: dashboards/settings/project/templates/project/settings.html:6
+msgid "OpenStack API"
+msgstr "OpenStack API"
+
+#: dashboards/settings/project/tables.py:27
+msgid "Service Name"
+msgstr "Nome do Serviço"
+
+#: dashboards/settings/project/tables.py:29
+msgid "Service Endpoint"
+msgstr "Terminal de Serviço"
+
+#: dashboards/settings/project/tables.py:33
+msgid "API Endpoints"
+msgstr "Terminal de API"
+
+#: dashboards/settings/project/templates/project/_openrc.html:15
+msgid "Download OpenStack RC File"
+msgstr "Baixar arquivo OpenStack RC"
+
+#: dashboards/settings/project/templates/project/_openrc.html:25
+msgid ""
+"Download the RC file for the selected project, then type \"source openrc\" "
+"in the terminal to configure your environment to communicate with OpenStack."
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:30
+msgid "Download RC File"
+msgstr "Baixar arquivo RC"
+
+#: dashboards/settings/user/forms.py:57
+msgid "Settings saved."
+msgstr "Configurações Salvo"
+
+#: dashboards/settings/user/panel.py:25
+#: dashboards/settings/user/templates/user/_settings.html:8
+#: dashboards/settings/user/templates/user/settings.html:3
+#: dashboards/settings/user/templates/user/settings.html:6
+msgid "User Settings"
+msgstr "Configuração do Usuário"
+
+#: dashboards/settings/user/templates/user/_settings.html:18
+msgid "From here you can modify dashboard settings for your user."
+msgstr ""
+"A partir daí você pode modificar as configurações do painel para o seu "
+"usuário."
+
#: templates/403.html:4 templates/403.html.py:9
msgid "Forbidden"
msgstr "Proibido"
@@ -83,10 +3281,6 @@ msgstr "Proibido"
msgid "Home"
msgstr "Página Inicial"
-#: templates/403.html:24 templates/404.html:23 templates/500.html:23
-msgid "Projects"
-msgstr "Projetos"
-
#: templates/404.html:4
msgid "Page Not Found"
msgstr "Página não encontrada"
@@ -112,3 +3306,47 @@ msgid ""
msgstr ""
"Ocorreu um erro inesperado ao processar o seu pedido. Por favor, tente "
"novamente."
+
+#: templates/_header.html:3
+msgid "Logged in as"
+msgstr "Logado como:"
+
+#: templates/_header.html:6
+msgid "Help"
+msgstr "Ajuda"
+
+#: templates/_header.html:8
+msgid "Sign Out"
+msgstr "Sair"
+
+#: test/settings.py:50
+msgid "Password must be between 8 and 18 characters."
+msgstr "As senhas devem ter entre 8 e 18 caracteres."
+
+#: usage/base.py:97
+msgid "Unable to retrieve usage information."
+msgstr "Não foi possível obter informações de utilização."
+
+#: usage/base.py:100
+msgid "You are viewing data for the future, which may or may not exist."
+msgstr "Você está visualizando dados do futuro, que podem ou não existir."
+
+#: usage/tables.py:11
+msgid "Download CSV Summary"
+msgstr "Baixar Resumo em CSV"
+
+#: usage/tables.py:25
+msgid "VCPU Hours"
+msgstr "Horas VCPU"
+
+#: usage/tables.py:32
+msgid "Disk GB Hours"
+msgstr "Horas GB Disco"
+
+#: usage/tables.py:40 usage/tables.py:68
+msgid "Usage Summary"
+msgstr "Resumo de Utilização"
+
+#: usage/tables.py:60
+msgid "Uptime"
+msgstr ""
diff --git a/openstack_dashboard/locale/ru/LC_MESSAGES/django.mo b/openstack_dashboard/locale/ru/LC_MESSAGES/django.mo
new file mode 100644
index 000000000..465fe029e
--- /dev/null
+++ b/openstack_dashboard/locale/ru/LC_MESSAGES/django.mo
Binary files differ
diff --git a/openstack_dashboard/locale/ru/LC_MESSAGES/django.po b/openstack_dashboard/locale/ru/LC_MESSAGES/django.po
new file mode 100644
index 000000000..2025d5a9a
--- /dev/null
+++ b/openstack_dashboard/locale/ru/LC_MESSAGES/django.po
@@ -0,0 +1,3297 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-10-05 19:30+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
+
+#: settings.py:142
+msgid "Bulgarian (Bulgaria)"
+msgstr ""
+
+#: settings.py:143
+msgid "Czech"
+msgstr ""
+
+#: settings.py:144
+msgid "English"
+msgstr ""
+
+#: settings.py:145
+msgid "Spanish"
+msgstr ""
+
+#: settings.py:146
+msgid "French"
+msgstr ""
+
+#: settings.py:147
+msgid "Italiano"
+msgstr ""
+
+#: settings.py:148
+msgid "Japanese"
+msgstr ""
+
+#: settings.py:149
+msgid "Korean (Korea)"
+msgstr ""
+
+#: settings.py:150
+msgid "Dutch (Netherlands)"
+msgstr ""
+
+#: settings.py:151
+msgid "Polish"
+msgstr ""
+
+#: settings.py:152
+msgid "Portuguese"
+msgstr ""
+
+#: settings.py:153
+msgid "Portuguese (Brazil)"
+msgstr ""
+
+#: settings.py:154
+msgid "Simplified Chinese"
+msgstr ""
+
+#: settings.py:155
+msgid "Traditional Chinese"
+msgstr ""
+
+#: api/keystone.py:56
+#, python-format
+msgid "%(type)s (%(backend)s backend)"
+msgstr ""
+
+#: api/nova.py:191
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(group)s"
+msgstr ""
+
+#: api/nova.py:196
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(cidr)s"
+msgstr ""
+
+#: api/nova.py:532
+msgid "Unknown instance"
+msgstr ""
+
+#: api/swift.py:217
+msgid "Unicode is not currently supported for object copy."
+msgstr ""
+
+#: dashboards/admin/dashboard.py:24
+msgid "System Panel"
+msgstr ""
+
+#: dashboards/admin/dashboard.py:30
+msgid "Admin"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:36 dashboards/admin/networks/forms.py:34
+#: dashboards/admin/networks/forms.py:69
+#: dashboards/admin/networks/ports/forms.py:40
+#: dashboards/admin/networks/ports/forms.py:72
+#: dashboards/admin/networks/ports/tables.py:73
+#: dashboards/admin/networks/subnets/tables.py:70
+#: dashboards/admin/projects/tables.py:87
+#: dashboards/admin/projects/workflows.py:71
+#: dashboards/admin/services/tables.py:38
+#: dashboards/admin/volumes/tables.py:10
+#: dashboards/project/access_and_security/security_groups/forms.py:36
+#: dashboards/project/access_and_security/security_groups/tables.py:58
+#: dashboards/project/images_and_snapshots/images/forms.py:40
+#: dashboards/project/images_and_snapshots/images/forms.py:115
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:9
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:10
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:77
+#: dashboards/project/instances/templates/instances/_detail_overview.html:9
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:9
+#: dashboards/project/networks/forms.py:37
+#: dashboards/project/networks/tables.py:94
+#: dashboards/project/networks/ports/tables.py:40
+#: dashboards/project/networks/subnets/forms.py:43
+#: dashboards/project/networks/subnets/forms.py:102
+#: dashboards/project/networks/subnets/tables.py:82
+#: dashboards/project/networks/templates/networks/_detail_overview.html:7
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:9
+#: dashboards/project/volumes/tables.py:144
+#: dashboards/project/volumes/tables.py:164
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:9
+msgid "Name"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:37 dashboards/admin/flavors/tables.py:41
+#: dashboards/admin/projects/workflows.py:39
+#: dashboards/project/instances/templates/instances/_detail_overview.html:26
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:10
+#: usage/tables.py:19
+msgid "VCPUs"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:38
+msgid "RAM MB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:39
+msgid "Root Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:40
+msgid "Ephemeral Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:50
+msgid "Unable to get unique ID for new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:67
+#, python-format
+msgid "Created flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:71
+msgid "Unable to create flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:92
+#, python-format
+msgid "Updated flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:96
+msgid "Unable to update flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/panel.py:29 dashboards/admin/flavors/tables.py:15
+#: dashboards/admin/flavors/tables.py:52
+#: dashboards/admin/flavors/templates/flavors/index.html:3
+#: dashboards/admin/flavors/templates/flavors/index.html:6
+msgid "Flavors"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:14
+#: dashboards/project/instances/workflows.py:177
+#: dashboards/project/instances/templates/instances/_detail_overview.html:22
+msgid "Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:23
+#: dashboards/admin/flavors/templates/flavors/_create.html:8
+#: dashboards/admin/flavors/templates/flavors/_create.html:23
+#: dashboards/admin/flavors/templates/flavors/create.html:3
+#: dashboards/admin/flavors/templates/flavors/create.html:6
+msgid "Create Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:30
+#: dashboards/admin/flavors/templates/flavors/_edit.html:8
+#: dashboards/admin/flavors/templates/flavors/edit.html:3
+#: dashboards/admin/flavors/templates/flavors/edit.html:6
+msgid "Edit Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:36
+#, python-format
+msgid "%sMB"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:40
+msgid "Flavor Name"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:43
+#: dashboards/project/instances/templates/instances/_detail_overview.html:24
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: usage/tables.py:22
+msgid "RAM"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:45
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+msgid "Root Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:47
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+msgid "Ephemeral Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:49
+msgid "Unable to retrieve flavor list."
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:76
+msgid "Unable to retrieve flavor data."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:17
+#: dashboards/admin/flavors/templates/flavors/_edit.html:17
+#: dashboards/admin/images/templates/images/_update.html:17
+#: dashboards/admin/networks/templates/networks/_create.html:17
+#: dashboards/admin/networks/templates/networks/ports/_create.html:17
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:17
+#: dashboards/admin/projects/tables.py:89
+#: dashboards/admin/projects/workflows.py:74
+#: dashboards/admin/projects/templates/projects/_add_user.html:17
+#: dashboards/admin/projects/templates/projects/_create.html:17
+#: dashboards/admin/projects/templates/projects/_create_user.html:17
+#: dashboards/admin/projects/templates/projects/_quotas.html:16
+#: dashboards/admin/projects/templates/projects/_update.html:17
+#: dashboards/admin/users/templates/users/_create.html:16
+#: dashboards/admin/users/templates/users/_update.html:16
+#: dashboards/project/access_and_security/security_groups/forms.py:38
+#: dashboards/project/access_and_security/security_groups/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:17
+#: dashboards/project/containers/templates/containers/_copy.html:16
+#: dashboards/project/containers/templates/containers/_create.html:16
+#: dashboards/project/containers/templates/containers/_upload.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/_create.html:16
+#: dashboards/project/networks/templates/networks/subnets/_create.html:17
+#: dashboards/project/volumes/forms.py:28
+#: dashboards/project/volumes/forms.py:195
+#: dashboards/project/volumes/tables.py:147
+#: dashboards/project/volumes/templates/volumes/_create.html:18
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:17
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:14
+msgid "Description"
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:18
+msgid "From here you can define the sizing of a new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:24
+#: dashboards/admin/flavors/templates/flavors/_edit.html:25
+#: dashboards/admin/images/templates/images/_update.html:24
+#: dashboards/admin/networks/templates/networks/_create.html:24
+#: dashboards/admin/networks/templates/networks/_update.html:23
+#: dashboards/admin/networks/templates/networks/ports/_create.html:24
+#: dashboards/admin/networks/templates/networks/ports/_update.html:28
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:24
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:32
+#: dashboards/admin/projects/templates/projects/_add_user.html:24
+#: dashboards/admin/projects/templates/projects/_create.html:24
+#: dashboards/admin/projects/templates/projects/_create_user.html:24
+#: dashboards/admin/projects/templates/projects/_quotas.html:23
+#: dashboards/admin/projects/templates/projects/_update.html:24
+#: dashboards/admin/users/templates/users/_create.html:23
+#: dashboards/admin/users/templates/users/_update.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:32
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:20
+#: dashboards/project/containers/templates/containers/_copy.html:23
+#: dashboards/project/containers/templates/containers/_create.html:23
+#: dashboards/project/containers/templates/containers/_upload.html:24
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:32
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:24
+#: dashboards/project/instances/templates/instances/_update.html:23
+#: dashboards/project/networks/templates/networks/_create.html:23
+#: dashboards/project/networks/templates/networks/_update.html:23
+#: dashboards/project/networks/templates/networks/subnets/_create.html:24
+#: dashboards/project/networks/templates/networks/subnets/_update.html:32
+#: dashboards/project/volumes/templates/volumes/_attach.html:24
+#: dashboards/project/volumes/templates/volumes/_create.html:56
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:24
+#: dashboards/settings/ec2/templates/ec2/download_form.html:24
+#: dashboards/settings/project/templates/project/_openrc.html:31
+#: dashboards/settings/user/templates/user/_settings.html:24
+msgid "Cancel"
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:18
+msgid "From here you can alter the sizing of the current flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:19
+msgid ""
+"Note: this will not affect the resources allocated to any existing instances "
+"using this flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:24
+#: dashboards/admin/projects/workflows.py:270
+#: dashboards/settings/user/templates/user/_settings.html:23
+msgid "Save"
+msgstr ""
+
+#: dashboards/admin/images/panel.py:29 dashboards/admin/images/tables.py:44
+#: dashboards/admin/images/templates/images/index.html:3
+#: dashboards/admin/images/templates/images/index.html:6
+#: dashboards/project/images_and_snapshots/images/tables.py:47
+#: dashboards/project/images_and_snapshots/images/tables.py:132
+msgid "Images"
+msgstr ""
+
+#: dashboards/admin/images/tables.py:40
+#: dashboards/project/images_and_snapshots/images/tables.py:113
+#: dashboards/project/instances/templates/instances/_detail_overview.html:74
+msgid "Image Name"
+msgstr ""
+
+#: dashboards/admin/images/views.py:55
+msgid "Unable to retrieve image list."
+msgstr ""
+
+#: dashboards/admin/images/templates/images/_update.html:8
+#: dashboards/admin/images/templates/images/_update.html:23
+#: dashboards/admin/images/templates/images/update.html:4
+#: dashboards/admin/images/templates/images/update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:22
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:6
+msgid "Update Image"
+msgstr ""
+
+#: dashboards/admin/images/templates/images/_update.html:18
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:17
+msgid "From here you can modify different properties of an image."
+msgstr ""
+
+#: dashboards/admin/instances/panel.py:29
+#: dashboards/admin/instances/tables.py:94
+#: dashboards/admin/instances/templates/instances/index.html:3
+#: dashboards/admin/projects/workflows.py:40
+#: dashboards/project/instances/panel.py:25
+#: dashboards/project/instances/tables.py:70
+#: dashboards/project/instances/tables.py:90
+#: dashboards/project/instances/tables.py:107
+#: dashboards/project/instances/tables.py:136
+#: dashboards/project/instances/tables.py:313
+#: dashboards/project/instances/templates/instances/index.html:3
+#: dashboards/project/instances/templates/instances/index.html:6
+msgid "Instances"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:60 usage/tables.py:30
+msgid "Project Name"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:67
+#: dashboards/admin/services/tables.py:40
+msgid "Host"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:71
+#: dashboards/project/instances/tables.py:290
+#: dashboards/project/instances/workflows.py:176 usage/tables.py:57
+msgid "Instance Name"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:72
+#: dashboards/project/access_and_security/floating_ips/tables.py:111
+#: dashboards/project/access_and_security/floating_ips/workflows.py:32
+#: dashboards/project/access_and_security/floating_ips/workflows.py:39
+#: dashboards/project/instances/tables.py:291
+msgid "IP Address"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:74
+#: dashboards/project/containers/tables.py:256
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:30
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:37
+#: dashboards/project/instances/tables.py:293
+#: dashboards/project/volumes/tables.py:150
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:26
+msgid "Size"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:79
+#: dashboards/admin/networks/tables.py:74
+#: dashboards/admin/networks/ports/tables.py:77
+#: dashboards/project/images_and_snapshots/images/tables.py:119
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:13
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:18
+#: dashboards/project/instances/tables.py:298
+#: dashboards/project/instances/templates/instances/_detail_overview.html:13
+#: dashboards/project/networks/tables.py:100
+#: dashboards/project/networks/ports/tables.py:44
+#: dashboards/project/networks/templates/networks/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:30
+#: dashboards/project/volumes/tables.py:154
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:17
+msgid "Status"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:83
+#: dashboards/project/instances/tables.py:302
+msgid "Task"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:90
+#: dashboards/project/instances/tables.py:309
+msgid "Power State"
+msgstr ""
+
+#: dashboards/admin/instances/views.py:49
+#: dashboards/project/access_and_security/views.py:76
+#: dashboards/project/access_and_security/floating_ips/workflows.py:65
+msgid "Unable to retrieve instance list."
+msgstr ""
+
+#: dashboards/admin/instances/views.py:63
+#: dashboards/admin/networks/views.py:48
+msgid "Unable to retrieve instance tenant information."
+msgstr ""
+
+#: dashboards/admin/instances/views.py:80
+#: dashboards/project/instances/views.py:82
+msgid "Unable to retrieve instance size information."
+msgstr ""
+
+#: dashboards/admin/instances/templates/instances/index.html:6
+msgid "All Instances"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:36
+#: dashboards/admin/networks/tables.py:67
+#: dashboards/admin/projects/tables.py:65 dashboards/project/dashboard.py:40
+#: dashboards/project/instances/workflows.py:38
+msgid "Project"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:37 dashboards/admin/networks/forms.py:74
+#: dashboards/admin/networks/tables.py:72
+#: dashboards/project/networks/tables.py:98
+#: dashboards/project/networks/templates/networks/_detail_overview.html:17
+msgid "Shared"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:46 dashboards/admin/users/forms.py:42
+msgid "Select a project"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:58
+#, python-format
+msgid "Network %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:64
+#, python-format
+msgid "Failed to create network %s"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:71
+#: dashboards/admin/networks/templates/networks/ports/_update.html:12
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:12
+#: dashboards/admin/users/forms.py:114
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:11
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:12
+#: dashboards/project/instances/templates/instances/_detail_overview.html:11
+#: dashboards/project/networks/forms.py:39
+#: dashboards/project/networks/templates/networks/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_update.html:12
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:11
+msgid "ID"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:82
+#: dashboards/project/networks/forms.py:48
+#, python-format
+msgid "Network %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:87
+#: dashboards/project/networks/forms.py:53
+#, python-format
+msgid "Failed to update network %s"
+msgstr ""
+
+#: dashboards/admin/networks/panel.py:25
+#: dashboards/admin/networks/tables.py:35
+#: dashboards/admin/networks/tables.py:80
+#: dashboards/admin/networks/templates/networks/index.html:3
+#: dashboards/admin/networks/templates/networks/index.html:6
+#: dashboards/project/instances/workflows.py:412
+#: dashboards/project/networks/panel.py:25
+#: dashboards/project/networks/tables.py:44
+#: dashboards/project/networks/tables.py:106
+#: dashboards/project/networks/templates/networks/index.html:3
+#: dashboards/project/networks/templates/networks/index.html:6
+msgid "Networks"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:34
+#: dashboards/project/networks/tables.py:43
+#: dashboards/project/networks/templates/networks/subnets/index.html:3
+#: dashboards/project/networks/templates/networks/subnets/index.html:6
+msgid "Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:41
+#: dashboards/project/networks/tables.py:59
+#, python-format
+msgid "Failed to delete network %s"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:49
+#: dashboards/admin/networks/templates/networks/_create.html:8
+#: dashboards/admin/networks/templates/networks/_create.html:23
+#: dashboards/admin/networks/templates/networks/create.html:3
+#: dashboards/admin/networks/templates/networks/create.html:6
+#: dashboards/project/networks/tables.py:67
+#: dashboards/project/networks/workflows.py:111
+#: dashboards/project/networks/templates/networks/_create.html:7
+#: dashboards/project/networks/templates/networks/_create.html:22
+#: dashboards/project/networks/templates/networks/create.html:3
+#: dashboards/project/networks/templates/networks/create.html:6
+msgid "Create Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:56
+#: dashboards/admin/networks/templates/networks/_update.html:7
+#: dashboards/project/networks/tables.py:74
+#: dashboards/project/networks/templates/networks/_update.html:7
+msgid "Edit Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:68
+#: dashboards/admin/networks/ports/forms.py:33
+#: dashboards/project/networks/subnets/forms.py:35
+msgid "Network Name"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:71
+#: dashboards/project/networks/tables.py:97
+msgid "Subnets Associated"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:76
+#: dashboards/admin/networks/ports/tables.py:79
+#: dashboards/project/networks/tables.py:102
+#: dashboards/project/networks/ports/tables.py:46
+#: dashboards/project/networks/templates/networks/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:32
+msgid "Admin State"
+msgstr ""
+
+#: dashboards/admin/networks/views.py:60
+#: dashboards/project/networks/views.py:52
+msgid "Network list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:91
+#: dashboards/project/networks/views.py:109
+msgid "Subnet list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:103
+#: dashboards/project/networks/views.py:121
+msgid "Port list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:118
+#: dashboards/project/networks/views.py:134
+#: dashboards/project/networks/subnets/tables.py:96
+#, python-format
+msgid "Unable to retrieve details for network \"%s\"."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:36
+#: dashboards/project/networks/subnets/forms.py:39
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:13
+msgid "Network ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:42
+#: dashboards/admin/networks/ports/forms.py:74
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:34
+msgid "Device ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:54
+#, python-format
+msgid "Port %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:59
+#, python-format
+msgid "Failed to create a port for network %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:84
+#, python-format
+msgid "Port %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:89
+#, python-format
+msgid "Failed to update port %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:34
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:6
+msgid "Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:35
+#: dashboards/admin/networks/ports/tables.py:83
+#: dashboards/project/networks/ports/tables.py:53
+msgid "Ports"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:41
+#: dashboards/admin/networks/subnets/tables.py:39
+#: dashboards/project/networks/subnets/tables.py:51
+#, python-format
+msgid "Failed to delete subnet %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:51
+#: dashboards/admin/networks/templates/networks/ports/_create.html:8
+#: dashboards/admin/networks/templates/networks/ports/_create.html:23
+#: dashboards/admin/networks/templates/networks/ports/create.html:3
+#: dashboards/admin/networks/templates/networks/ports/create.html:6
+msgid "Create Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:62
+#: dashboards/admin/networks/templates/networks/ports/_update.html:7
+msgid "Edit Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:75
+#: dashboards/project/networks/ports/tables.py:42
+msgid "Fixed IPs"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:76
+#: dashboards/project/networks/ports/tables.py:43
+msgid "Device Attached"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tabs.py:32
+#: dashboards/admin/overview/panel.py:29
+#: dashboards/admin/overview/templates/overview/usage.html:6
+#: dashboards/project/images_and_snapshots/images/tabs.py:27
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:27
+#: dashboards/project/instances/tabs.py:26
+#: dashboards/project/networks/ports/tabs.py:32
+#: dashboards/project/networks/subnets/tabs.py:32
+#: dashboards/project/overview/panel.py:29
+#: dashboards/project/overview/templates/overview/usage.html:6
+#: dashboards/project/volumes/tabs.py:27
+msgid "Overview"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tabs.py:42
+#: dashboards/project/networks/ports/tabs.py:42
+msgid "Unable to retrieve port details."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:49
+#: dashboards/admin/networks/subnets/views.py:49
+#: dashboards/project/networks/subnets/views.py:54
+msgid "Unable to retrieve network."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:82
+msgid "Unable to retrieve port details"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/forms.py:43
+#, python-format
+msgid "Failed to retrieve network %s for a subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:32
+#: dashboards/project/networks/subnets/tables.py:44
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:6
+msgid "Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:33
+#: dashboards/admin/networks/subnets/tables.py:81
+#: dashboards/project/networks/subnets/tables.py:45
+#: dashboards/project/networks/subnets/tables.py:104
+msgid "Subnets"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:49
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:8
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:23
+#: dashboards/admin/networks/templates/networks/subnets/create.html:3
+#: dashboards/admin/networks/templates/networks/subnets/create.html:6
+#: dashboards/project/networks/workflows.py:53
+#: dashboards/project/networks/subnets/tables.py:61
+#: dashboards/project/networks/templates/networks/subnets/_create.html:8
+#: dashboards/project/networks/templates/networks/subnets/_create.html:23
+#: dashboards/project/networks/templates/networks/subnets/create.html:3
+#: dashboards/project/networks/templates/networks/subnets/create.html:6
+msgid "Create Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:60
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:7
+#: dashboards/project/networks/subnets/tables.py:72
+#: dashboards/project/networks/templates/networks/subnets/_update.html:7
+msgid "Edit Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:72
+#: dashboards/project/access_and_security/security_groups/forms.py:91
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:15
+msgid "CIDR"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:73
+#: dashboards/project/networks/workflows.py:66
+#: dashboards/project/networks/subnets/forms.py:53
+#: dashboards/project/networks/subnets/tables.py:85
+msgid "IP Version"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:74
+#: dashboards/project/networks/subnets/forms.py:54
+#: dashboards/project/networks/subnets/forms.py:104
+#: dashboards/project/networks/subnets/tables.py:86
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:19
+msgid "Gateway IP"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/views.py:82
+#: dashboards/project/networks/subnets/views.py:86
+msgid "Unable to retrieve subnet details"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_create.html:18
+#: dashboards/project/networks/templates/networks/_create.html:17
+msgid "Select a name for your network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:16
+#: dashboards/admin/networks/templates/networks/ports/_update.html:21
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:25
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:17
+#: dashboards/project/instances/templates/instances/_update.html:16
+#: dashboards/project/networks/templates/networks/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_update.html:25
+#: dashboards/settings/ec2/templates/ec2/download_form.html:17
+#: dashboards/settings/project/templates/project/_openrc.html:24
+#: dashboards/settings/user/templates/user/_settings.html:17
+msgid "Description:"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:17
+#: dashboards/project/networks/templates/networks/_update.html:17
+msgid "You may update the editable properties of your network here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:22
+#: dashboards/admin/networks/templates/networks/ports/_update.html:27
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:31
+#: dashboards/project/instances/templates/instances/_update.html:22
+#: dashboards/project/networks/templates/networks/_update.html:22
+#: dashboards/project/networks/templates/networks/subnets/_update.html:31
+msgid "Save Changes"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/update.html:3
+#: dashboards/admin/networks/templates/networks/update.html:6
+#: dashboards/project/networks/templates/networks/update.html:3
+#: dashboards/project/networks/templates/networks/update.html:6
+msgid "Update Network"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_create.html:18
+msgid ""
+"You can create a port for the network. If you specify device ID to be "
+"attached, the device specified will be attached to the port created."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_update.html:22
+msgid "You may update the editable properties of your port here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/update.html:3
+#: dashboards/admin/networks/templates/networks/ports/update.html:6
+msgid "Update Port"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:18
+#: dashboards/project/networks/templates/networks/subnets/_create.html:18
+msgid ""
+"You can create a subnet for the network. Any network address can be "
+"specified unless the network address does not overlap other subnets in the "
+"network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:14
+#: dashboards/project/networks/workflows.py:58
+#: dashboards/project/networks/subnets/forms.py:45
+#: dashboards/project/networks/subnets/tables.py:84
+#: dashboards/project/networks/templates/networks/subnets/_update.html:14
+msgid "Network Address"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:17
+#: dashboards/project/networks/templates/networks/subnets/_update.html:16
+msgid "IP version"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:26
+#: dashboards/project/networks/templates/networks/subnets/_update.html:26
+msgid "You may update the editable properties of your subnet here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/index.html:3
+#: dashboards/admin/networks/templates/networks/subnets/index.html:6
+#: dashboards/project/networks/templates/networks/detail.html:3
+msgid "Network Detail"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/update.html:3
+#: dashboards/admin/networks/templates/networks/subnets/update.html:6
+#: dashboards/project/networks/templates/networks/subnets/update.html:3
+#: dashboards/project/networks/templates/networks/subnets/update.html:6
+msgid "Update Subnet"
+msgstr ""
+
+#: dashboards/admin/overview/templates/overview/usage.html:3
+msgid "Usage Overview"
+msgstr ""
+
+#: dashboards/admin/overview/templates/overview/usage.html:12
+msgid "Monitoring"
+msgstr ""
+
+#: dashboards/admin/projects/panel.py:29
+#: dashboards/admin/projects/tables.py:66
+#: dashboards/admin/projects/tables.py:95
+#: dashboards/admin/projects/templates/projects/index.html:8
+#: templates/403.html:24 templates/404.html:23 templates/500.html:23
+msgid "Projects"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:19
+msgid "Modify Users"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:32
+msgid "View Usage"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:39
+#: dashboards/admin/projects/templates/projects/_create.html:8
+#: dashboards/admin/projects/templates/projects/_create.html:23
+#: dashboards/admin/projects/templates/projects/create.html:6
+msgid "Create Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:46
+#: dashboards/admin/projects/workflows.py:269
+#: dashboards/admin/projects/templates/projects/update.html:3
+#: dashboards/admin/projects/templates/projects/update.html:6
+msgid "Edit Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:90
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:60
+#: dashboards/project/networks/templates/networks/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:15
+msgid "Project ID"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:91
+#: dashboards/admin/projects/workflows.py:76
+#: dashboards/admin/projects/workflows.py:251
+#: dashboards/admin/services/tables.py:42 dashboards/admin/users/tables.py:40
+#: dashboards/admin/users/tables.py:115
+msgid "Enabled"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:104
+msgid "Remove"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:105
+msgid "Removed"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:106 dashboards/admin/users/tables.py:41
+#: dashboards/admin/users/tables.py:75
+#: dashboards/project/instances/workflows.py:39
+msgid "User"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:107 dashboards/admin/users/panel.py:29
+#: dashboards/admin/users/tables.py:42 dashboards/admin/users/tables.py:76
+#: dashboards/admin/users/tables.py:122
+#: dashboards/admin/users/templates/users/index.html:8
+msgid "Users"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:125
+msgid "Unable to retrieve role information."
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:130
+msgid "Roles"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:134
+msgid "Users For Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:142
+msgid "Add To Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:154
+msgid "Add New Users"
+msgstr ""
+
+#: dashboards/admin/projects/views.py:67
+msgid "Unable to retrieve project information."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:87
+msgid "Unable to retrieve project list."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:110
+msgid "Unable to retrieve users."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:154
+msgid "Unable to retrieve default quota values."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:182
+msgid "Unable to retrieve project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:37
+msgid "Injected File Content Bytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:38
+msgid "Metadata Items"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:41
+msgid "Injected Files"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:44
+#: dashboards/admin/volumes/panel.py:9 dashboards/admin/volumes/tables.py:15
+#: dashboards/admin/volumes/templates/volumes/index.html:3
+#: dashboards/admin/volumes/templates/volumes/index.html:6
+#: dashboards/project/volumes/panel.py:25
+#: dashboards/project/volumes/tables.py:38
+#: dashboards/project/volumes/tables.py:171
+#: dashboards/project/volumes/tables.py:183
+#: dashboards/project/volumes/templates/volumes/index.html:3
+#: dashboards/project/volumes/templates/volumes/index.html:6
+msgid "Volumes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:45
+msgid "Gigabytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:46
+msgid "RAM (MB)"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:47
+#: dashboards/project/access_and_security/floating_ips/tables.py:50
+#: dashboards/project/access_and_security/floating_ips/tables.py:128
+msgid "Floating IPs"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:50
+msgid "Quota"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:52
+msgid "From here you can set quotas (max limits) for the project."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:81
+#: dashboards/admin/projects/workflows.py:254
+msgid "Project Info"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:82
+#: dashboards/admin/projects/templates/projects/_create.html:18
+msgid "From here you can create a new project to organize users."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:101
+msgid "Unable to retrieve user list. Please try again later."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:155
+#: dashboards/admin/projects/templates/projects/_update_members.html:16
+msgid "Project Members"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:169
+#: dashboards/admin/users/views.py:47
+msgid "Unable to retrieve user list."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:180
+msgid "Add Project"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:181
+msgid "Finish"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:182
+#, python-format
+msgid "Created new project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:183
+#, python-format
+msgid "Unable to create project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:227
+#, python-format
+msgid "Failed to add %s project members and set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:246
+msgid "Unable to set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:256
+msgid "From here you can edit the project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:271
+#, python-format
+msgid "Modified project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:272
+#, python-format
+msgid "Unable to modify project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:342
+#, python-format
+msgid "Failed to modify %s project members and update project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:363
+msgid ""
+"Modified project information and members, but unable to modify project "
+"quotas."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:8
+#: dashboards/admin/projects/templates/projects/add_user.html:3
+#: dashboards/admin/projects/templates/projects/add_user.html:6
+msgid "Add User To Project"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:18
+msgid "Select the user role for the project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:23
+msgid "Add"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:7
+#, python-format
+msgid "Create User for project '%(tenant_name)s'."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:18
+msgid "From here you can create a new user to add to this project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:23
+#: dashboards/admin/users/tables.py:20
+#: dashboards/admin/users/templates/users/_create.html:7
+#: dashboards/admin/users/templates/users/_create.html:22
+#: dashboards/admin/users/templates/users/create.html:7
+msgid "Create User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:7
+#: dashboards/admin/projects/templates/projects/_quotas.html:22
+msgid "Update Quota"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:17
+#, python-format
+msgid ""
+"From here you can edit quotas (max limits) for the project %(tenant.name)s."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update.html:8
+#: dashboards/admin/projects/templates/projects/_update.html:23
+#: dashboards/admin/projects/templates/projects/quotas.html:6
+msgid "Update Project"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update.html:18
+msgid "From here you can edit a project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:7
+msgid ""
+"From here you can add and remove members to this project from the list of "
+"all available users."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:10
+msgid "All Users"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:25
+#: dashboards/admin/projects/templates/projects/_update_members.html:32
+msgid "No users found."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/create_user.html:3
+#: dashboards/admin/projects/templates/projects/create_user.html:6
+msgid "Add New User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:3
+msgid "Project Usage Overview"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:7
+msgid "Project Usage"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/users.html:7
+msgid "Users for Project"
+msgstr ""
+
+#: dashboards/admin/quotas/panel.py:29 dashboards/admin/quotas/tables.py:36
+msgid "Quotas"
+msgstr ""
+
+#: dashboards/admin/quotas/tables.py:28
+msgid "Quota Name"
+msgstr ""
+
+#: dashboards/admin/quotas/tables.py:29
+msgid "Limit"
+msgstr ""
+
+#: dashboards/admin/quotas/views.py:46
+msgid "Unable to get quota info."
+msgstr ""
+
+#: dashboards/admin/quotas/templates/quotas/index.html:8
+msgid "Default Quotas"
+msgstr ""
+
+#: dashboards/admin/services/panel.py:29
+#: dashboards/admin/services/tables.py:47
+#: dashboards/admin/services/templates/services/index.html:8
+msgid "Services"
+msgstr ""
+
+#: dashboards/admin/services/tables.py:37
+msgid "Id"
+msgstr ""
+
+#: dashboards/admin/services/tables.py:39
+msgid "Service"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:54
+msgid "Passwords do not match."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:62 dashboards/admin/users/forms.py:115
+#: dashboards/admin/users/tables.py:108
+msgid "User Name"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:63 dashboards/admin/users/forms.py:116
+#: dashboards/admin/users/tables.py:109
+msgid "Email"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:65 dashboards/admin/users/forms.py:117
+msgid "Password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:70 dashboards/admin/users/forms.py:124
+msgid "Confirm Password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:73 dashboards/admin/users/forms.py:127
+msgid "Primary Project"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:75
+msgid "Role"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:96
+#, python-format
+msgid "User \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:106
+msgid "Unable to add userto primary project."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:110
+msgid "Unable to create user."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:151
+msgid "name"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:151
+msgid "email"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:160
+msgid "primary project"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:173
+#, python-format
+msgid "The user %s has no role defined for"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:181
+msgid "password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:190
+msgid "User has been updated successfully."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:194
+#, python-format
+msgid "Unable to update %(attributes)s for the user."
+msgstr ""
+
+#: dashboards/admin/users/tables.py:32
+#: dashboards/project/images_and_snapshots/images/tables.py:68
+msgid "Edit"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:39
+msgid "Enable"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:39
+msgid "Disable"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:40
+msgid "Disabled"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:63
+msgid "You cannot disable the user you are currently logged in as."
+msgstr ""
+
+#: dashboards/admin/users/tables.py:114
+msgid "User ID"
+msgstr ""
+
+#: dashboards/admin/users/views.py:70
+msgid "Unable to update user."
+msgstr ""
+
+#: dashboards/admin/users/views.py:104
+msgid "Unable to retrieve user roles."
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_create.html:17
+msgid "From here you can create a new user and assign them to a project."
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_update.html:7
+#: dashboards/admin/users/templates/users/_update.html:22
+#: dashboards/admin/users/templates/users/update.html:7
+msgid "Update User"
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_update.html:17
+msgid ""
+"From here you can edit the user's details, including their default project."
+msgstr ""
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:3
+#: dashboards/project/volumes/templates/volumes/detail.html:3
+msgid "Volume Details"
+msgstr ""
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:6
+#: dashboards/project/volumes/templates/volumes/detail.html:6
+msgid "Volume Detail"
+msgstr ""
+
+#: dashboards/project/dashboard.py:24
+msgid "Manage Compute"
+msgstr ""
+
+#: dashboards/project/dashboard.py:35
+msgid "Object Store"
+msgstr ""
+
+#: dashboards/project/access_and_security/panel.py:26
+#: dashboards/project/instances/workflows.py:348
+msgid "Access & Security"
+msgstr ""
+
+#: dashboards/project/access_and_security/views.py:51
+msgid "Unable to retrieve keypair list."
+msgstr ""
+
+#: dashboards/project/access_and_security/views.py:60
+#: dashboards/project/access_and_security/security_groups/views.py:74
+msgid "Unable to retrieve security groups."
+msgstr ""
+
+#: dashboards/project/access_and_security/views.py:69
+#: dashboards/project/access_and_security/floating_ips/workflows.py:49
+msgid "Unable to retrieve floating IP addresses."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:32
+msgid "Pool"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:43
+#, python-format
+msgid "Allocated Floating IP %(ip)s."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:47
+msgid "Unable to allocate Floating IP."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:37
+msgid "Allocate IP To Project"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:47
+msgid "Release"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:48
+msgid "Released"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:49
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:22
+msgid "Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:6
+#: dashboards/project/instances/tables.py:219
+msgid "Associate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:76
+msgid "Disassociate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:90
+#, python-format
+msgid "Successfully disassociated Floating IP: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:94
+msgid "Unable to disassociate floating IP."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:114
+#: dashboards/project/access_and_security/floating_ips/workflows.py:36
+#: dashboards/project/instances/tables.py:69
+#: dashboards/project/instances/tables.py:89
+#: dashboards/project/instances/tables.py:106
+#: dashboards/project/instances/tables.py:135
+#: dashboards/project/volumes/tables.py:206
+msgid "Instance"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:117
+msgid "Floating IP Pool"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:65
+msgid "Unable to retrieve floating IP pools."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:68
+msgid "No floating IP pools available."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:40
+msgid "Select the IP address you wish to associate with the selected instance."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:53
+msgid "Select an IP address"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:55
+msgid "No IP addresses available"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:76
+#: dashboards/project/volumes/forms.py:160
+msgid "Select an instance"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:78
+#: dashboards/project/volumes/forms.py:162
+msgid "No instances available"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:97
+msgid "Manage Floating IP Associations"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:98
+msgid "Associate"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:99
+#, python-format
+msgid "IP address %s associated."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:100
+#, python-format
+msgid "Unable to associate IP address %s."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:38
+#: dashboards/project/access_and_security/keypairs/forms.py:49
+#: dashboards/project/access_and_security/keypairs/tables.py:52
+msgid "Keypair Name"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:40
+msgid ""
+"Keypair names may only contain letters, numbers, underscores and hyphens."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:51
+msgid "Public Key"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:60
+#, python-format
+msgid "Successfully imported public key: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:65
+msgid "Unable to import keypair."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:30
+#: dashboards/project/instances/tables.py:295
+#: dashboards/project/instances/workflows.py:335
+msgid "Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:31
+#: dashboards/project/access_and_security/keypairs/tables.py:60
+msgid "Keypairs"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:39
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html:6
+msgid "Import Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:46
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html:6
+msgid "Create Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/tables.py:53
+msgid "Fingerprint"
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/views.py:74
+#, python-format
+msgid "Unable to create keypair: %(exc)s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:46
+#, python-format
+msgid "Successfully created security group: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:52
+msgid "Unable to create security group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:57
+#: dashboards/project/access_and_security/security_groups/tables.py:93
+msgid "IP Protocol"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:61
+msgid "The protocol which this rule should be applied to."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:65
+#: dashboards/project/access_and_security/security_groups/forms.py:71
+#: dashboards/project/access_and_security/security_groups/tables.py:95
+msgid "From Port"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:66
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP type in the range (-1: 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:72
+#: dashboards/project/images_and_snapshots/images/tables.py:115
+msgid "Type"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:74
+#: dashboards/project/access_and_security/security_groups/forms.py:80
+#: dashboards/project/access_and_security/security_groups/tables.py:96
+msgid "To Port"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:75
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP code in the range (-1: 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:81
+msgid "Code"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:84
+msgid "Source Group"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:86
+msgid ""
+"To specify an allowed IP range, select CIDR. To allow access from all "
+"members of another security group select Source Group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:94
+msgid "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:121
+msgid "The ICMP type is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:124
+msgid "The ICMP code is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:127
+msgid "The ICMP type not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:130
+msgid "The ICMP code not in range (-1, 255)"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:134
+msgid "The \"from\" port number is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:137
+msgid "The \"to\" port number is invalid."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:140
+msgid ""
+"The \"to\" port number must be greater than or equal to the \"from\" port "
+"number."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:146
+msgid "Either CIDR or Source Group may be specified, but not both."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:168
+#, python-format
+msgid "Successfully added rule: %s"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:173
+msgid "Unable to add rule to security group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:31
+msgid "Security Group"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:32
+#: dashboards/project/access_and_security/security_groups/tables.py:66
+#: dashboards/project/instances/workflows.py:340
+#: dashboards/project/instances/templates/instances/_detail_overview.html:49
+msgid "Security Groups"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:45
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html:6
+msgid "Create Security Group"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:52
+msgid "Edit Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:72
+msgid "Rule"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:73
+msgid "Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:97
+msgid "Source"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/tables.py:107
+msgid "Security Group Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/views.py:60
+msgid "Unable to retrieve security group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/views.py:80
+#, python-format
+msgid "%s (current)"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/index.html:6
+msgid "Access &amp; Security"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:8
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html:3
+msgid "Allocate Floating IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:18
+msgid "Allocate a floating IP from a given floating ip pool."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:20
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:19
+msgid "Project Quotas"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:31
+msgid "Allocate IP"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:17
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:17
+msgid ""
+"Keypairs are ssh credentials which are injected into images when they are "
+"launched. Creating a new key pair registers the public key and downloads the "
+"private key (a .pem file)."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:18
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:18
+msgid "Protect and use the key as you would any normal ssh private key."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:6
+msgid "Download Keypair"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:11
+#, python-format
+msgid ""
+"The keypair &quot;%(keypair_name)s&quot; should download automatically. If "
+"not use the link below."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:15
+#, python-format
+msgid "Download keypair &quot;%(keypair_name)s&quot;"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:18
+msgid "From here you can create a new security group"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:9
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html:6
+msgid "Edit Security Group Rules"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:12
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:19
+msgid "Add Rule"
+msgstr ""
+
+#: dashboards/project/containers/browsers.py:26
+msgid "Swift"
+msgstr ""
+
+#: dashboards/project/containers/browsers.py:29
+#: dashboards/project/containers/tables.py:40
+msgid "Container"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:39
+msgid "Slash is not an allowed character."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:49
+#: dashboards/project/containers/tables.py:121
+msgid "Container Name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:57
+msgid "Container created successfully."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:68
+msgid "Folder created successfully."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:71
+msgid "Unable to create container."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:79
+#: dashboards/project/containers/tables.py:253
+msgid "Object Name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:81
+msgid "File"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:95
+msgid "Object was successfully uploaded."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:98
+msgid "Unable to upload object."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:102
+msgid "Destination container"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:106
+msgid "Destination object name"
+msgstr ""
+
+#: dashboards/project/containers/forms.py:137
+#: dashboards/project/containers/forms.py:163
+msgid "Unable to copy object."
+msgstr ""
+
+#: dashboards/project/containers/forms.py:153
+#, python-format
+msgid "Copied \"%(orig)s\" to \"%(dest)s\" as \"%(new)s\"."
+msgstr ""
+
+#: dashboards/project/containers/panel.py:29
+#: dashboards/project/containers/tables.py:41
+#: dashboards/project/containers/tables.py:128
+#: dashboards/project/containers/templates/containers/index.html:7
+msgid "Containers"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:62
+#: dashboards/project/containers/templates/containers/_create.html:7
+#: dashboards/project/containers/templates/containers/_create.html:22
+#: dashboards/project/containers/templates/containers/create.html:6
+msgid "Create Container"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:69
+msgid "View Container"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:81
+#: dashboards/project/containers/templates/containers/_upload.html:23
+#: dashboards/project/containers/templates/containers/upload.html:3
+msgid "Upload Object"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:137
+#: dashboards/project/containers/tables.py:156
+msgid "Object"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:138
+#: dashboards/project/containers/tables.py:157
+#: dashboards/project/containers/tables.py:263
+msgid "Objects"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:149
+msgid "Folder"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:150
+msgid "Folders"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:163
+msgid "Copy"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:176
+msgid "Download"
+msgstr ""
+
+#: dashboards/project/containers/tables.py:232
+msgid "Create Folder"
+msgstr ""
+
+#: dashboards/project/containers/views.py:53
+msgid "Unable to retrieve container list."
+msgstr ""
+
+#: dashboards/project/containers/views.py:82
+msgid "Unable to retrieve object list."
+msgstr ""
+
+#: dashboards/project/containers/views.py:166
+msgid "Unable to retrieve object."
+msgstr ""
+
+#: dashboards/project/containers/views.py:200
+msgid "Unable to list containers."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_copy.html:7
+#: dashboards/project/containers/templates/containers/_copy.html:22
+#: dashboards/project/containers/templates/containers/copy.html:3
+#: dashboards/project/containers/templates/containers/copy.html:6
+msgid "Copy Object"
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_copy.html:17
+msgid ""
+"Make a new copy of an existing object to store in this or another container. "
+"You may also specify a path at which the new copy should live inside of the "
+"selected container."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_create.html:17
+msgid ""
+"A container is a storage compartment for your data and provides a way for "
+"you to organize your data. You can think of a container as a folder in "
+"Windows &reg; or a directory in UNIX &reg;. The primary difference between a "
+"container and these other file system concepts is that containers cannot be "
+"nested. You can, however, create an unlimited number of containers within "
+"your account. Data must be stored in a container so you must have at least "
+"one container defined in your account prior to uploading data."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:8
+msgid "Upload Object To Container"
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:18
+msgid ""
+"An object is the basic storage entity and any optional metadata that "
+"represents the files you store in the OpenStack Object Storage system. When "
+"you upload data to OpenStack Object Storage, the data is stored as-is (no "
+"compression or encryption) and consists of a location (container), the "
+"object's name, and any metadata consisting of key/value pairs."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/upload.html:6
+msgid "Upload Objects"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/panel.py:26
+msgid "Images & Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:63
+msgid "Unable to retrieve images."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:74
+msgid "Unable to retrieve snapshots."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/views.py:82
+#: dashboards/project/volumes/forms.py:65
+msgid "Unable to retrieve volume snapshots."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:42
+msgid "Image Location"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:43
+msgid "An external (HTTP) URL to load the image from."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:46
+#: dashboards/project/images_and_snapshots/images/forms.py:130
+#: dashboards/project/images_and_snapshots/images/tables.py:126
+msgid "Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:50
+msgid "AKI - Amazon Kernel Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:53
+msgid "AMI - Amazon Machine Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:56
+msgid "ARI - Amazon Ramdisk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:59
+msgid "ISO - Optical Disk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:61
+msgid "QCOW2 - QEMU Emulator"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:68
+msgid "Minimum Disk (GB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:69
+#: dashboards/project/images_and_snapshots/images/forms.py:76
+msgid ""
+"The minimum disk size required to boot the image. If unspecified, this value "
+"defaults to 0 (no minimum)."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:75
+msgid "Minimum Ram (MB)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:82
+#: dashboards/project/images_and_snapshots/images/forms.py:134
+#: dashboards/project/images_and_snapshots/images/tables.py:123
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:15
+msgid "Public"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:106
+#, python-format
+msgid "Your image %s has been queued for creation."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:110
+msgid "Unable to create new image."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:116
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:48
+msgid "Kernel ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:121
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:52
+msgid "Ramdisk ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:126
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:44
+msgid "Architecture"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:138
+#, python-format
+msgid "Unable to update image \"%s\"."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:162
+msgid "Image was successfully updated."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tables.py:34
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:33
+#: dashboards/project/instances/workflows.py:455
+msgid "Launch"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tables.py:46
+#: dashboards/project/images_and_snapshots/images/tables.py:82
+#: dashboards/project/instances/workflows.py:168
+#: dashboards/project/instances/workflows.py:173
+msgid "Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tables.py:61
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:31
+msgid "Create Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/tabs.py:38
+msgid "Unable to retrieve image details."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/views.py:61
+msgid "Unable to retrieve image."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:37
+msgid "Instance ID"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:40
+#: dashboards/project/volumes/forms.py:193
+msgid "Snapshot Name"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:50
+#, python-format
+msgid "Snapshot \"%(name)s\" created for instance \"%(inst)s\""
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:56
+msgid "Unable to create snapshot."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:48
+#: dashboards/project/instances/workflows.py:107
+#: dashboards/project/instances/workflows.py:169
+msgid "Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:49
+msgid "Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:55
+msgid "Instance Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/snapshots/views.py:53
+msgid "Unable to retrieve instance."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:6
+msgid "Images &amp; Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:6
+msgid "Create An Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:18
+msgid "Specify an image to upload to the Image Service."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:21
+msgid ""
+"Currently only images available via an HTTP URL are supported. The image "
+"location must be accessible to the Image Service. Compressed image binaries "
+"are supported (.zip and .tar.gz.)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:24
+msgid "Please note: "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:25
+msgid ""
+"The Image Location field MUST be a valid and direct URL to the image binary. "
+"URLs that redirect or serve error pages will result in unusable images."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:3
+msgid "Image Overview"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:6
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:7
+#: dashboards/project/instances/templates/instances/_detail_overview.html:6
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:6
+msgid "Info"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:17
+msgid "Checksum"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:19
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:39
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:28
+msgid "Created"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:21
+msgid "Updated"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:27
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:34
+#: dashboards/project/instances/templates/instances/_detail_overview.html:19
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:23
+msgid "Specs"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:32
+msgid "Container Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:34
+msgid "Disk Format"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:40
+msgid "Custom Properties"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:56
+msgid "Euca2ools state"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:64
+msgid "Image Type"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html:4
+msgid "Image Detail "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:8
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:3
+#: dashboards/project/instances/tables.py:179
+#: dashboards/project/volumes/tables.py:76
+msgid "Create Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:18
+msgid "Snapshots preserve the disk state of a running instance."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:20
+#: dashboards/project/instances/workflows.py:75
+#: dashboards/project/instances/workflows.py:110
+#: dashboards/project/instances/templates/instances/_detail_overview.html:93
+#: dashboards/project/volumes/tables.py:37
+#: dashboards/project/volumes/tables.py:182
+msgid "Volume"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:38
+#: dashboards/project/instances/templates/instances/_detail_overview.html:29
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:27
+msgid "GB"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:6
+msgid "Create a Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:3
+msgid "Volume Snapshot Details"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:6
+msgid "Volume Snapshot Detail"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:34
+#: dashboards/project/instances/workflows.py:76
+msgid "Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:35
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:85
+msgid "Volume Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:43
+#: dashboards/project/volumes/tables.py:59
+#: dashboards/project/volumes/templates/volumes/_create.html:8
+#: dashboards/project/volumes/templates/volumes/_create.html:55
+msgid "Create Volume"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:80
+#: dashboards/project/volumes/forms.py:26
+msgid "Volume Name"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:41
+msgid "Unable to retrieve snapshot details."
+msgstr ""
+
+#: dashboards/project/instances/forms.py:45
+#, python-format
+msgid "Instance \"%s\" updated."
+msgstr ""
+
+#: dashboards/project/instances/forms.py:50
+msgid "Unable to update instance."
+msgstr ""
+
+#: dashboards/project/instances/tables.py:67
+msgid "Terminate"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:68
+msgid "Scheduled termination of"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:87
+msgid "Reboot"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:88
+msgid "Rebooted"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:104
+msgid "Pause"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:104
+msgid "Unpause"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:105
+msgid "Paused"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:105
+msgid "Unpaused"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:133
+msgid "Suspend"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:133
+msgid "Resume"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:134
+msgid "Suspended"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:134
+msgid "Resumed"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:162
+#: dashboards/project/instances/workflows.py:454
+#: dashboards/project/instances/templates/instances/launch.html:3
+#: dashboards/project/instances/templates/instances/launch.html:6
+msgid "Launch Instance"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:169
+#: dashboards/project/instances/templates/instances/_update.html:7
+msgid "Edit Instance"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:189
+msgid "VNC Console"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:204
+msgid "View Log"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:252
+#, python-format
+msgid "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disk"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:259
+#: dashboards/project/instances/tables.py:266
+msgid "Not available"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:36
+msgid "Log"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:48
+#: dashboards/project/instances/views.py:106
+#, python-format
+msgid "Unable to get log for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:55
+msgid "VNC"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:70
+#: dashboards/project/instances/views.py:122
+#, python-format
+msgid "Unable to get VNC console for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/views.py:59
+msgid "Unable to retrieve instances."
+msgstr ""
+
+#: dashboards/project/instances/views.py:144
+msgid "Unable to retrieve instance details."
+msgstr ""
+
+#: dashboards/project/instances/views.py:179
+#, python-format
+msgid "Unable to retrieve details for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:53
+msgid "Project & User"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:66
+msgid "Don't boot from a volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:67
+msgid "Boot from volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:68
+msgid "Boot from volume snapshot (creates a new volume)."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:72
+#: dashboards/project/instances/workflows.py:90
+msgid "Volume Options"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:78
+#: dashboards/project/volumes/forms.py:126
+msgid "Device Name"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:81
+msgid "Volume mount point (e.g. 'vda' mounts at '/dev/vda')."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:83
+msgid "Delete on Terminate"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:86
+msgid "Delete volume on instance terminate"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:100
+#, python-format
+msgid "Please choose a volume, or select %s."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:117
+msgid "Select Volume"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:125
+msgid "Unable to retrieve list of volumes."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:129
+msgid "Select Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:138
+msgid "Unable to retrieve list of volume snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:171
+msgid "Instance Source"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:174
+msgid "Instance Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:178
+msgid "Size of image to launch."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:179
+msgid "Instance Count"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:182
+msgid "Number of instances to launch."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:185
+msgid "Details"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:198
+msgid ""
+"There are no image sources available; you must first create an image before "
+"attempting to launch an instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:203
+msgid "Please select an option for the instance source."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:212
+msgid ""
+"Launching multiple instances is only supported for images and instance "
+"snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:229
+msgid "Unable to retrieve public images."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:244
+msgid "Unable to retrieve images for the current project."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:267
+msgid "Select Image"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:269
+msgid "No images available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:278
+msgid "Select Instance Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:280
+msgid "No snapshots available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:291
+msgid "Unable to retrieve instance flavors."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:304 usage/base.py:114
+msgid "Unable to retrieve quota information."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:337
+msgid "Which keypair to use for authentication."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:344
+msgid "Launch instance in these security groups."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:349
+msgid ""
+"Control access to your instance via keypairs, security groups, and other "
+"mechanisms."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:359
+msgid "Unable to retrieve keypairs."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:361
+msgid "Select a keypair"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:363
+msgid "No keypairs available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:372
+msgid "Unable to retrieve list of security groups"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:392
+msgid "Customization Script"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:394
+msgid ""
+"A script or set of commands to be executed after the instance has been built "
+"(max 16kb)."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:401
+msgid "Post-Creation"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:415
+msgid "Launch instance withthese networks"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:419
+msgid "Networking"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:421
+msgid "Select networks for your instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:433
+msgid "Unable to retrieve networks."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:456
+#, python-format
+msgid "Launched %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:457
+#, python-format
+msgid "Unable to launch %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:470
+#, python-format
+msgid "%s instances"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:473
+msgid "instance"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:4
+msgid "Instance Console Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:7
+msgid "Log Length"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:9
+msgid "Go"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:11
+msgid "View Full Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:3
+msgid "Instance Overview"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:27
+msgid "VCPU"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:28
+#: usage/tables.py:20
+msgid "Disk"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:34
+msgid "IP Addresses"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:59
+msgid "No rules defined."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:68
+msgid "Meta"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:71
+msgid "Key Name"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:84
+msgid "Volumes Attached"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:88
+#: dashboards/project/volumes/tables.py:167
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:38
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:45
+msgid "Attached To"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:90
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:42
+msgid "on"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:94
+msgid "No volumes attached."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:3
+msgid "Instance VNC Console"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid ""
+"If VNC console is not responding to keyboard input: click the grey status "
+"bar below."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid "Click here to show only VNC"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:8
+msgid "VNC console is currently unavailabe. Please try again later."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:9
+msgid "Reload"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:2
+msgid ""
+"You can customize your instance after it's launched using the options "
+"available here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:3
+msgid ""
+"The \"Customization Script\" field is analogous to \"User Data\" in other "
+"systems."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:3
+msgid "Specify the details for launching an instance."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:4
+msgid ""
+"The chart below shows the resources used by this project in relation to the "
+"project's quotas."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:6
+msgid "Flavor Details"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+msgid "Total Disk"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "MB"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:21
+msgid "Number of Instances"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:29
+msgid "Number of VCPUs"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "Total RAM"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_volumes_help.html:3
+msgid ""
+"An instance can be launched with varying types of attached storage. You may "
+"select from those options here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_update.html:17
+msgid "You may update the editable properties of your instance here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/detail.html:3
+msgid "Instance Detail"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/update.html:3
+#: dashboards/project/instances/templates/instances/update.html:6
+msgid "Update Instance"
+msgstr ""
+
+#: dashboards/project/networks/tables.py:81
+msgid "Add Subnet"
+msgstr ""
+
+#: dashboards/project/networks/views.py:86
+msgid "Unable to retrieve network details."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:37
+msgid "Network Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:42
+msgid ""
+"From here you can create a new network.\n"
+"In addition a subnet associated with the network can be created in the next "
+"panel."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:56
+msgid "Subnet Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:61
+#: dashboards/project/networks/subnets/forms.py:48
+msgid "Network address in CIDR format (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:67
+msgid "Gateway IP (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:70
+#: dashboards/project/networks/subnets/forms.py:57
+#: dashboards/project/networks/subnets/forms.py:107
+msgid "IP address of Gateway (e.g. 192.168.0.1)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:77
+msgid ""
+"You can create a subnet associated with the new network, in which case "
+"\"Network Address\" must be specified. If you wish to create a network "
+"WITHOUT a subnet, uncheck the \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:89
+msgid "Specify \"Network Address\" or clear \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:94
+#: dashboards/project/networks/subnets/forms.py:70
+msgid "Network Address and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:98
+#: dashboards/project/networks/subnets/forms.py:74
+#: dashboards/project/networks/subnets/forms.py:119
+msgid "Gateway IP and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:112
+msgid "Create"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:113
+#, python-format
+msgid "Created network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:114
+#, python-format
+msgid "Unable to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:130
+#, python-format
+msgid "Network \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:133
+#, python-format
+msgid "Failed to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:152
+#, python-format
+msgid "Subnet \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:155
+#, python-format
+msgid "Failed to create subnet \"%(sub)s\" for network \"%(net)s\"."
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Attached"
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Detached"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:85
+#, python-format
+msgid "Subnet %s was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:90
+#, python-format
+msgid "Failed to create subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:131
+#, python-format
+msgid "Subnet %s was successfully updated."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:136
+#, python-format
+msgid "Failed to update subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/tabs.py:42
+msgid "Unable to retrieve subnet details."
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/_detail_overview.html:3
+msgid "Network Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/detail.html:6
+msgid "Network Detail: "
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:3
+msgid "Port Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:17
+msgid "Fixed IP"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:21
+msgid "IP address:"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:22
+msgid "Subnet ID"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:28
+msgid "Mac Address"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/detail.html:3
+#: dashboards/project/networks/templates/networks/ports/detail.html:6
+msgid "Port Detail"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:3
+msgid "Subnet Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:21
+msgid "IP allocation pool"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:24
+msgid "Start"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:25
+msgid " - End"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/detail.html:3
+#: dashboards/project/networks/templates/networks/subnets/detail.html:6
+msgid "Subnet Detail"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:29
+msgid "Size (GB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:30
+msgid "Use snapshot as a source"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:49
+#, python-format
+msgid "Volume size must be equal to or greater than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:54
+msgid "Unable to load the specified snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:59
+msgid "Choose a snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:83
+#, python-format
+msgid "The volume size cannot be less than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:92
+#, python-format
+msgid ""
+"A volume of %(req)iGB cannot be created as you only have %(avail)iGB of your "
+"quota available."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:99
+msgid "You are already using all of your available volumes."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:115
+msgid "Unable to create volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:123
+msgid "Attach to Instance"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:124
+msgid "Select an instance to attach to."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:168
+msgid "Unknown instance (None)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:179
+#, python-format
+msgid "Attaching volume %(vol)s to instance %(inst)s on %(dev)s."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:188
+msgid "Unable to attach volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:212
+#, python-format
+msgid "Creating volume snapshot \"%s\""
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:218
+msgid "Unable to create volume snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:46
+#, python-format
+msgid "Unable to delete volume \"%s\". One or more snapshots depend on it."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:66
+msgid "Edit Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:93
+#, python-format
+msgid "%sGB"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:106
+#: dashboards/project/volumes/views.py:149
+msgid "Unable to retrieve attachment information."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:123
+#, python-format
+msgid "Attached to %(instance)s on %(dev)s"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:180
+msgid "Detach"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:181
+msgid "Detaching"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:216
+#, python-format
+msgid "%(dev)s on instance %(instance_name)s"
+msgstr ""
+
+#: dashboards/project/volumes/tabs.py:42
+msgid "Unable to retrieve volume details."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:50
+msgid "Unable to retrieve volume list."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:58
+msgid "Unable to retrieve volume/instance attachment information"
+msgstr ""
+
+#: dashboards/project/volumes/views.py:130
+#: dashboards/project/volumes/views.py:140
+msgid "Unable to retrieve volume information."
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:9
+#: dashboards/project/volumes/templates/volumes/attach.html:6
+msgid "Manage Volume Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:13
+msgid "Attach To Instance"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:22
+msgid "Attach Volume"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:20
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:18
+msgid "Volumes are block devices that can be attached to instances."
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:22
+msgid "Volume Quotas"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:25
+msgid "Total Gigabytes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:34
+msgid "Number of Volumes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:8
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:23
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:3
+msgid "Create Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:3
+msgid "Volume Overview"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:34
+msgid "Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:46
+msgid "Not attached"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/create.html:6
+msgid "Create a Volume"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:6
+msgid "Create a Volume Snapshot"
+msgstr ""
+
+#: dashboards/settings/dashboard.py:24 templates/_header.html:4
+msgid "Settings"
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:36 dashboards/settings/project/forms.py:36
+msgid "Select a Project"
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:46
+msgid "Unable to retrieve tenant list."
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:88
+msgid "Unable to fetch EC2 credentials."
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:101
+#, python-format
+msgid "Error writing zipfile: %(exc)s"
+msgstr ""
+
+#: dashboards/settings/ec2/panel.py:25
+msgid "EC2 Credentials"
+msgstr ""
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:8
+#: dashboards/settings/ec2/templates/ec2/download_form.html:23
+#: dashboards/settings/ec2/templates/ec2/index.html:3
+#: dashboards/settings/ec2/templates/ec2/index.html:6
+msgid "Download EC2 Credentials"
+msgstr ""
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:18
+msgid ""
+"Clicking \"Download EC2 Credentials\" will download a zip file which "
+"includes an rc file with your access/secret keys, as well as your x509 "
+"private key and certificate."
+msgstr ""
+
+#: dashboards/settings/project/forms.py:71
+#, python-format
+msgid "Error Downloading RC File: %s"
+msgstr ""
+
+#: dashboards/settings/project/panel.py:25
+#: dashboards/settings/project/templates/project/_openrc.html:8
+#: dashboards/settings/project/templates/project/settings.html:3
+#: dashboards/settings/project/templates/project/settings.html:6
+msgid "OpenStack API"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:27
+msgid "Service Name"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:29
+msgid "Service Endpoint"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:33
+msgid "API Endpoints"
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:15
+msgid "Download OpenStack RC File"
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:25
+msgid ""
+"Download the RC file for the selected project, then type \"source openrc\" "
+"in the terminal to configure your environment to communicate with OpenStack."
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:30
+msgid "Download RC File"
+msgstr ""
+
+#: dashboards/settings/user/forms.py:57
+msgid "Settings saved."
+msgstr ""
+
+#: dashboards/settings/user/panel.py:25
+#: dashboards/settings/user/templates/user/_settings.html:8
+#: dashboards/settings/user/templates/user/settings.html:3
+#: dashboards/settings/user/templates/user/settings.html:6
+msgid "User Settings"
+msgstr ""
+
+#: dashboards/settings/user/templates/user/_settings.html:18
+msgid "From here you can modify dashboard settings for your user."
+msgstr ""
+
+#: templates/403.html:4 templates/403.html.py:9
+msgid "Forbidden"
+msgstr ""
+
+#: templates/403.html:20 templates/404.html:19 templates/500.html:19
+msgid "Home"
+msgstr ""
+
+#: templates/404.html:4
+msgid "Page Not Found"
+msgstr ""
+
+#: templates/404.html:9
+msgid "The page you were looking for doesn't exist"
+msgstr ""
+
+#: templates/404.html:10
+msgid "You may have mistyped the address or the page may have moved."
+msgstr ""
+
+#: templates/500.html:4 templates/500.html.py:9
+msgid "Internal Server Error"
+msgstr ""
+
+#: templates/500.html:10
+msgid ""
+"An unexpected error occurred while processing your request. Please try your "
+"request again."
+msgstr ""
+
+#: templates/_header.html:3
+msgid "Logged in as"
+msgstr ""
+
+#: templates/_header.html:6
+msgid "Help"
+msgstr ""
+
+#: templates/_header.html:8
+msgid "Sign Out"
+msgstr ""
+
+#: test/settings.py:50
+msgid "Password must be between 8 and 18 characters."
+msgstr ""
+
+#: usage/base.py:97
+msgid "Unable to retrieve usage information."
+msgstr ""
+
+#: usage/base.py:100
+msgid "You are viewing data for the future, which may or may not exist."
+msgstr ""
+
+#: usage/tables.py:11
+msgid "Download CSV Summary"
+msgstr ""
+
+#: usage/tables.py:25
+msgid "VCPU Hours"
+msgstr ""
+
+#: usage/tables.py:32
+msgid "Disk GB Hours"
+msgstr ""
+
+#: usage/tables.py:40 usage/tables.py:68
+msgid "Usage Summary"
+msgstr ""
+
+#: usage/tables.py:60
+msgid "Uptime"
+msgstr ""
diff --git a/openstack_dashboard/locale/zh_CN/LC_MESSAGES/django.mo b/openstack_dashboard/locale/zh_CN/LC_MESSAGES/django.mo
index 66a90e824..4eb099617 100644
--- a/openstack_dashboard/locale/zh_CN/LC_MESSAGES/django.mo
+++ b/openstack_dashboard/locale/zh_CN/LC_MESSAGES/django.mo
Binary files differ
diff --git a/openstack_dashboard/locale/zh_CN/LC_MESSAGES/django.po b/openstack_dashboard/locale/zh_CN/LC_MESSAGES/django.po
index 15f78aef2..4c62683d2 100644
--- a/openstack_dashboard/locale/zh_CN/LC_MESSAGES/django.po
+++ b/openstack_dashboard/locale/zh_CN/LC_MESSAGES/django.po
@@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Horizon\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-09-18 22:18+0000\n"
+"POT-Creation-Date: 2012-10-05 19:30+0000\n"
"PO-Revision-Date: 2012-09-11 08:10+0000\n"
"Last-Translator: daisy.ycguo <daisy.ycguo@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -19,63 +19,3219 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-#: settings.py:141
+#: settings.py:142
msgid "Bulgarian (Bulgaria)"
msgstr ""
-#: settings.py:142
+#: settings.py:143
msgid "Czech"
msgstr ""
-#: settings.py:143
+#: settings.py:144
msgid "English"
msgstr "英语"
-#: settings.py:144
+#: settings.py:145
msgid "Spanish"
msgstr "西班牙语"
-#: settings.py:145
+#: settings.py:146
msgid "French"
msgstr "法语"
-#: settings.py:146
+#: settings.py:147
msgid "Italiano"
msgstr "意大利语"
-#: settings.py:147
+#: settings.py:148
msgid "Japanese"
msgstr "日语"
-#: settings.py:148
+#: settings.py:149
msgid "Korean (Korea)"
msgstr ""
-#: settings.py:149
+#: settings.py:150
msgid "Dutch (Netherlands)"
msgstr ""
-#: settings.py:150
+#: settings.py:151
msgid "Polish"
msgstr "波兰语"
-#: settings.py:151
+#: settings.py:152
msgid "Portuguese"
msgstr "葡萄牙语"
-#: settings.py:152
+#: settings.py:153
#, fuzzy
msgid "Portuguese (Brazil)"
msgstr "葡萄牙语"
-#: settings.py:153
+#: settings.py:154
msgid "Simplified Chinese"
msgstr "简体中文"
-#: settings.py:154
+#: settings.py:155
msgid "Traditional Chinese"
msgstr "繁体中文"
+#: api/keystone.py:56
+#, python-format
+msgid "%(type)s (%(backend)s backend)"
+msgstr "%(type)s (%(backend)s 后端)"
+
+#: api/nova.py:191
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(group)s"
+msgstr "允许 %(from)s:%(to)s 来自 %(group)s"
+
+#: api/nova.py:196
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(cidr)s"
+msgstr "允许 %(from)s:%(to)s 来自 %(cidr)s"
+
+#: api/nova.py:532
+msgid "Unknown instance"
+msgstr "未知的实例名"
+
+#: api/swift.py:217
+msgid "Unicode is not currently supported for object copy."
+msgstr "块复制时,暂时不支持Unicode"
+
+#: dashboards/admin/dashboard.py:24
+msgid "System Panel"
+msgstr ""
+
+#: dashboards/admin/dashboard.py:30
+msgid "Admin"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:36 dashboards/admin/networks/forms.py:34
+#: dashboards/admin/networks/forms.py:69
+#: dashboards/admin/networks/ports/forms.py:40
+#: dashboards/admin/networks/ports/forms.py:72
+#: dashboards/admin/networks/ports/tables.py:73
+#: dashboards/admin/networks/subnets/tables.py:70
+#: dashboards/admin/projects/tables.py:87
+#: dashboards/admin/projects/workflows.py:71
+#: dashboards/admin/services/tables.py:38
+#: dashboards/admin/volumes/tables.py:10
+#: dashboards/project/access_and_security/security_groups/forms.py:36
+#: dashboards/project/access_and_security/security_groups/tables.py:58
+#: dashboards/project/images_and_snapshots/images/forms.py:40
+#: dashboards/project/images_and_snapshots/images/forms.py:115
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:9
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:10
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:77
+#: dashboards/project/instances/templates/instances/_detail_overview.html:9
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:9
+#: dashboards/project/networks/forms.py:37
+#: dashboards/project/networks/tables.py:94
+#: dashboards/project/networks/ports/tables.py:40
+#: dashboards/project/networks/subnets/forms.py:43
+#: dashboards/project/networks/subnets/forms.py:102
+#: dashboards/project/networks/subnets/tables.py:82
+#: dashboards/project/networks/templates/networks/_detail_overview.html:7
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:9
+#: dashboards/project/volumes/tables.py:144
+#: dashboards/project/volumes/tables.py:164
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:9
+msgid "Name"
+msgstr "名称"
+
+#: dashboards/admin/flavors/forms.py:37 dashboards/admin/flavors/tables.py:41
+#: dashboards/admin/projects/workflows.py:39
+#: dashboards/project/instances/templates/instances/_detail_overview.html:26
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:10
+#: usage/tables.py:19
+msgid "VCPUs"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:38
+msgid "RAM MB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:39
+msgid "Root Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:40
+msgid "Ephemeral Disk GB"
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:50
+msgid "Unable to get unique ID for new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:67
+#, python-format
+msgid "Created flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:71
+msgid "Unable to create flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:92
+#, python-format
+msgid "Updated flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:96
+msgid "Unable to update flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/panel.py:29 dashboards/admin/flavors/tables.py:15
+#: dashboards/admin/flavors/tables.py:52
+#: dashboards/admin/flavors/templates/flavors/index.html:3
+#: dashboards/admin/flavors/templates/flavors/index.html:6
+msgid "Flavors"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:14
+#: dashboards/project/instances/workflows.py:177
+#: dashboards/project/instances/templates/instances/_detail_overview.html:22
+msgid "Flavor"
+msgstr "类型"
+
+#: dashboards/admin/flavors/tables.py:23
+#: dashboards/admin/flavors/templates/flavors/_create.html:8
+#: dashboards/admin/flavors/templates/flavors/_create.html:23
+#: dashboards/admin/flavors/templates/flavors/create.html:3
+#: dashboards/admin/flavors/templates/flavors/create.html:6
+msgid "Create Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:30
+#: dashboards/admin/flavors/templates/flavors/_edit.html:8
+#: dashboards/admin/flavors/templates/flavors/edit.html:3
+#: dashboards/admin/flavors/templates/flavors/edit.html:6
+msgid "Edit Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:36
+#, python-format
+msgid "%sMB"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:40
+msgid "Flavor Name"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:43
+#: dashboards/project/instances/templates/instances/_detail_overview.html:24
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: usage/tables.py:22
+msgid "RAM"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:45
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+msgid "Root Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:47
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+msgid "Ephemeral Disk"
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:49
+msgid "Unable to retrieve flavor list."
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:76
+msgid "Unable to retrieve flavor data."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:17
+#: dashboards/admin/flavors/templates/flavors/_edit.html:17
+#: dashboards/admin/images/templates/images/_update.html:17
+#: dashboards/admin/networks/templates/networks/_create.html:17
+#: dashboards/admin/networks/templates/networks/ports/_create.html:17
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:17
+#: dashboards/admin/projects/tables.py:89
+#: dashboards/admin/projects/workflows.py:74
+#: dashboards/admin/projects/templates/projects/_add_user.html:17
+#: dashboards/admin/projects/templates/projects/_create.html:17
+#: dashboards/admin/projects/templates/projects/_create_user.html:17
+#: dashboards/admin/projects/templates/projects/_quotas.html:16
+#: dashboards/admin/projects/templates/projects/_update.html:17
+#: dashboards/admin/users/templates/users/_create.html:16
+#: dashboards/admin/users/templates/users/_update.html:16
+#: dashboards/project/access_and_security/security_groups/forms.py:38
+#: dashboards/project/access_and_security/security_groups/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:17
+#: dashboards/project/containers/templates/containers/_copy.html:16
+#: dashboards/project/containers/templates/containers/_create.html:16
+#: dashboards/project/containers/templates/containers/_upload.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/_create.html:16
+#: dashboards/project/networks/templates/networks/subnets/_create.html:17
+#: dashboards/project/volumes/forms.py:28
+#: dashboards/project/volumes/forms.py:195
+#: dashboards/project/volumes/tables.py:147
+#: dashboards/project/volumes/templates/volumes/_create.html:18
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:17
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:14
+msgid "Description"
+msgstr "描述"
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:18
+msgid "From here you can define the sizing of a new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:24
+#: dashboards/admin/flavors/templates/flavors/_edit.html:25
+#: dashboards/admin/images/templates/images/_update.html:24
+#: dashboards/admin/networks/templates/networks/_create.html:24
+#: dashboards/admin/networks/templates/networks/_update.html:23
+#: dashboards/admin/networks/templates/networks/ports/_create.html:24
+#: dashboards/admin/networks/templates/networks/ports/_update.html:28
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:24
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:32
+#: dashboards/admin/projects/templates/projects/_add_user.html:24
+#: dashboards/admin/projects/templates/projects/_create.html:24
+#: dashboards/admin/projects/templates/projects/_create_user.html:24
+#: dashboards/admin/projects/templates/projects/_quotas.html:23
+#: dashboards/admin/projects/templates/projects/_update.html:24
+#: dashboards/admin/users/templates/users/_create.html:23
+#: dashboards/admin/users/templates/users/_update.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:32
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:20
+#: dashboards/project/containers/templates/containers/_copy.html:23
+#: dashboards/project/containers/templates/containers/_create.html:23
+#: dashboards/project/containers/templates/containers/_upload.html:24
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:32
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:24
+#: dashboards/project/instances/templates/instances/_update.html:23
+#: dashboards/project/networks/templates/networks/_create.html:23
+#: dashboards/project/networks/templates/networks/_update.html:23
+#: dashboards/project/networks/templates/networks/subnets/_create.html:24
+#: dashboards/project/networks/templates/networks/subnets/_update.html:32
+#: dashboards/project/volumes/templates/volumes/_attach.html:24
+#: dashboards/project/volumes/templates/volumes/_create.html:56
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:24
+#: dashboards/settings/ec2/templates/ec2/download_form.html:24
+#: dashboards/settings/project/templates/project/_openrc.html:31
+#: dashboards/settings/user/templates/user/_settings.html:24
+msgid "Cancel"
+msgstr "取消"
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:18
+msgid "From here you can alter the sizing of the current flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:19
+msgid ""
+"Note: this will not affect the resources allocated to any existing instances "
+"using this flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:24
+#: dashboards/admin/projects/workflows.py:270
+#: dashboards/settings/user/templates/user/_settings.html:23
+msgid "Save"
+msgstr ""
+
+#: dashboards/admin/images/panel.py:29 dashboards/admin/images/tables.py:44
+#: dashboards/admin/images/templates/images/index.html:3
+#: dashboards/admin/images/templates/images/index.html:6
+#: dashboards/project/images_and_snapshots/images/tables.py:47
+#: dashboards/project/images_and_snapshots/images/tables.py:132
+msgid "Images"
+msgstr "镜像"
+
+#: dashboards/admin/images/tables.py:40
+#: dashboards/project/images_and_snapshots/images/tables.py:113
+#: dashboards/project/instances/templates/instances/_detail_overview.html:74
+msgid "Image Name"
+msgstr "镜像名称"
+
+#: dashboards/admin/images/views.py:55
+msgid "Unable to retrieve image list."
+msgstr ""
+
+#: dashboards/admin/images/templates/images/_update.html:8
+#: dashboards/admin/images/templates/images/_update.html:23
+#: dashboards/admin/images/templates/images/update.html:4
+#: dashboards/admin/images/templates/images/update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:22
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:6
+msgid "Update Image"
+msgstr ""
+
+#: dashboards/admin/images/templates/images/_update.html:18
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:17
+msgid "From here you can modify different properties of an image."
+msgstr ""
+
+#: dashboards/admin/instances/panel.py:29
+#: dashboards/admin/instances/tables.py:94
+#: dashboards/admin/instances/templates/instances/index.html:3
+#: dashboards/admin/projects/workflows.py:40
+#: dashboards/project/instances/panel.py:25
+#: dashboards/project/instances/tables.py:70
+#: dashboards/project/instances/tables.py:90
+#: dashboards/project/instances/tables.py:107
+#: dashboards/project/instances/tables.py:136
+#: dashboards/project/instances/tables.py:313
+#: dashboards/project/instances/templates/instances/index.html:3
+#: dashboards/project/instances/templates/instances/index.html:6
+msgid "Instances"
+msgstr "实例"
+
+#: dashboards/admin/instances/tables.py:60 usage/tables.py:30
+msgid "Project Name"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:67
+#: dashboards/admin/services/tables.py:40
+msgid "Host"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:71
+#: dashboards/project/instances/tables.py:290
+#: dashboards/project/instances/workflows.py:176 usage/tables.py:57
+msgid "Instance Name"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:72
+#: dashboards/project/access_and_security/floating_ips/tables.py:111
+#: dashboards/project/access_and_security/floating_ips/workflows.py:32
+#: dashboards/project/access_and_security/floating_ips/workflows.py:39
+#: dashboards/project/instances/tables.py:291
+msgid "IP Address"
+msgstr "IP地址"
+
+#: dashboards/admin/instances/tables.py:74
+#: dashboards/project/containers/tables.py:256
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:30
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:37
+#: dashboards/project/instances/tables.py:293
+#: dashboards/project/volumes/tables.py:150
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:26
+msgid "Size"
+msgstr "大小"
+
+#: dashboards/admin/instances/tables.py:79
+#: dashboards/admin/networks/tables.py:74
+#: dashboards/admin/networks/ports/tables.py:77
+#: dashboards/project/images_and_snapshots/images/tables.py:119
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:13
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:18
+#: dashboards/project/instances/tables.py:298
+#: dashboards/project/instances/templates/instances/_detail_overview.html:13
+#: dashboards/project/networks/tables.py:100
+#: dashboards/project/networks/ports/tables.py:44
+#: dashboards/project/networks/templates/networks/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:30
+#: dashboards/project/volumes/tables.py:154
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:17
+msgid "Status"
+msgstr "状态"
+
+#: dashboards/admin/instances/tables.py:83
+#: dashboards/project/instances/tables.py:302
+msgid "Task"
+msgstr ""
+
+#: dashboards/admin/instances/tables.py:90
+#: dashboards/project/instances/tables.py:309
+msgid "Power State"
+msgstr ""
+
+#: dashboards/admin/instances/views.py:49
+#: dashboards/project/access_and_security/views.py:76
+#: dashboards/project/access_and_security/floating_ips/workflows.py:65
+msgid "Unable to retrieve instance list."
+msgstr "找不到实例列表"
+
+#: dashboards/admin/instances/views.py:63
+#: dashboards/admin/networks/views.py:48
+msgid "Unable to retrieve instance tenant information."
+msgstr ""
+
+#: dashboards/admin/instances/views.py:80
+#: dashboards/project/instances/views.py:82
+msgid "Unable to retrieve instance size information."
+msgstr "无法获取实例的大小信息。"
+
+#: dashboards/admin/instances/templates/instances/index.html:6
+msgid "All Instances"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:36
+#: dashboards/admin/networks/tables.py:67
+#: dashboards/admin/projects/tables.py:65 dashboards/project/dashboard.py:40
+#: dashboards/project/instances/workflows.py:38
+msgid "Project"
+msgstr "工程"
+
+#: dashboards/admin/networks/forms.py:37 dashboards/admin/networks/forms.py:74
+#: dashboards/admin/networks/tables.py:72
+#: dashboards/project/networks/tables.py:98
+#: dashboards/project/networks/templates/networks/_detail_overview.html:17
+msgid "Shared"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:46 dashboards/admin/users/forms.py:42
+msgid "Select a project"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:58
+#, python-format
+msgid "Network %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:64
+#, python-format
+msgid "Failed to create network %s"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:71
+#: dashboards/admin/networks/templates/networks/ports/_update.html:12
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:12
+#: dashboards/admin/users/forms.py:114
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:11
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:12
+#: dashboards/project/instances/templates/instances/_detail_overview.html:11
+#: dashboards/project/networks/forms.py:39
+#: dashboards/project/networks/templates/networks/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_update.html:12
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:11
+msgid "ID"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:82
+#: dashboards/project/networks/forms.py:48
+#, python-format
+msgid "Network %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:87
+#: dashboards/project/networks/forms.py:53
+#, python-format
+msgid "Failed to update network %s"
+msgstr ""
+
+#: dashboards/admin/networks/panel.py:25
+#: dashboards/admin/networks/tables.py:35
+#: dashboards/admin/networks/tables.py:80
+#: dashboards/admin/networks/templates/networks/index.html:3
+#: dashboards/admin/networks/templates/networks/index.html:6
+#: dashboards/project/instances/workflows.py:412
+#: dashboards/project/networks/panel.py:25
+#: dashboards/project/networks/tables.py:44
+#: dashboards/project/networks/tables.py:106
+#: dashboards/project/networks/templates/networks/index.html:3
+#: dashboards/project/networks/templates/networks/index.html:6
+msgid "Networks"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:34
+#: dashboards/project/networks/tables.py:43
+#: dashboards/project/networks/templates/networks/subnets/index.html:3
+#: dashboards/project/networks/templates/networks/subnets/index.html:6
+msgid "Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:41
+#: dashboards/project/networks/tables.py:59
+#, python-format
+msgid "Failed to delete network %s"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:49
+#: dashboards/admin/networks/templates/networks/_create.html:8
+#: dashboards/admin/networks/templates/networks/_create.html:23
+#: dashboards/admin/networks/templates/networks/create.html:3
+#: dashboards/admin/networks/templates/networks/create.html:6
+#: dashboards/project/networks/tables.py:67
+#: dashboards/project/networks/workflows.py:111
+#: dashboards/project/networks/templates/networks/_create.html:7
+#: dashboards/project/networks/templates/networks/_create.html:22
+#: dashboards/project/networks/templates/networks/create.html:3
+#: dashboards/project/networks/templates/networks/create.html:6
+msgid "Create Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:56
+#: dashboards/admin/networks/templates/networks/_update.html:7
+#: dashboards/project/networks/tables.py:74
+#: dashboards/project/networks/templates/networks/_update.html:7
+msgid "Edit Network"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:68
+#: dashboards/admin/networks/ports/forms.py:33
+#: dashboards/project/networks/subnets/forms.py:35
+msgid "Network Name"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:71
+#: dashboards/project/networks/tables.py:97
+msgid "Subnets Associated"
+msgstr ""
+
+#: dashboards/admin/networks/tables.py:76
+#: dashboards/admin/networks/ports/tables.py:79
+#: dashboards/project/networks/tables.py:102
+#: dashboards/project/networks/ports/tables.py:46
+#: dashboards/project/networks/templates/networks/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:32
+msgid "Admin State"
+msgstr ""
+
+#: dashboards/admin/networks/views.py:60
+#: dashboards/project/networks/views.py:52
+msgid "Network list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:91
+#: dashboards/project/networks/views.py:109
+msgid "Subnet list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:103
+#: dashboards/project/networks/views.py:121
+msgid "Port list can not be retrieved."
+msgstr ""
+
+#: dashboards/admin/networks/views.py:118
+#: dashboards/project/networks/views.py:134
+#: dashboards/project/networks/subnets/tables.py:96
+#, python-format
+msgid "Unable to retrieve details for network \"%s\"."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:36
+#: dashboards/project/networks/subnets/forms.py:39
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:13
+msgid "Network ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:42
+#: dashboards/admin/networks/ports/forms.py:74
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:34
+msgid "Device ID"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:54
+#, python-format
+msgid "Port %s was successfully created."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:59
+#, python-format
+msgid "Failed to create a port for network %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:84
+#, python-format
+msgid "Port %s was successfully updated."
+msgstr ""
+
+#: dashboards/admin/networks/ports/forms.py:89
+#, python-format
+msgid "Failed to update port %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:34
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:6
+msgid "Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:35
+#: dashboards/admin/networks/ports/tables.py:83
+#: dashboards/project/networks/ports/tables.py:53
+msgid "Ports"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:41
+#: dashboards/admin/networks/subnets/tables.py:39
+#: dashboards/project/networks/subnets/tables.py:51
+#, python-format
+msgid "Failed to delete subnet %s"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:51
+#: dashboards/admin/networks/templates/networks/ports/_create.html:8
+#: dashboards/admin/networks/templates/networks/ports/_create.html:23
+#: dashboards/admin/networks/templates/networks/ports/create.html:3
+#: dashboards/admin/networks/templates/networks/ports/create.html:6
+msgid "Create Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:62
+#: dashboards/admin/networks/templates/networks/ports/_update.html:7
+msgid "Edit Port"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:75
+#: dashboards/project/networks/ports/tables.py:42
+msgid "Fixed IPs"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tables.py:76
+#: dashboards/project/networks/ports/tables.py:43
+msgid "Device Attached"
+msgstr ""
+
+#: dashboards/admin/networks/ports/tabs.py:32
+#: dashboards/admin/overview/panel.py:29
+#: dashboards/admin/overview/templates/overview/usage.html:6
+#: dashboards/project/images_and_snapshots/images/tabs.py:27
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:27
+#: dashboards/project/instances/tabs.py:26
+#: dashboards/project/networks/ports/tabs.py:32
+#: dashboards/project/networks/subnets/tabs.py:32
+#: dashboards/project/overview/panel.py:29
+#: dashboards/project/overview/templates/overview/usage.html:6
+#: dashboards/project/volumes/tabs.py:27
+msgid "Overview"
+msgstr "概述"
+
+#: dashboards/admin/networks/ports/tabs.py:42
+#: dashboards/project/networks/ports/tabs.py:42
+msgid "Unable to retrieve port details."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:49
+#: dashboards/admin/networks/subnets/views.py:49
+#: dashboards/project/networks/subnets/views.py:54
+msgid "Unable to retrieve network."
+msgstr ""
+
+#: dashboards/admin/networks/ports/views.py:82
+msgid "Unable to retrieve port details"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/forms.py:43
+#, python-format
+msgid "Failed to retrieve network %s for a subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:32
+#: dashboards/project/networks/subnets/tables.py:44
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:6
+msgid "Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:33
+#: dashboards/admin/networks/subnets/tables.py:81
+#: dashboards/project/networks/subnets/tables.py:45
+#: dashboards/project/networks/subnets/tables.py:104
+msgid "Subnets"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:49
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:8
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:23
+#: dashboards/admin/networks/templates/networks/subnets/create.html:3
+#: dashboards/admin/networks/templates/networks/subnets/create.html:6
+#: dashboards/project/networks/workflows.py:53
+#: dashboards/project/networks/subnets/tables.py:61
+#: dashboards/project/networks/templates/networks/subnets/_create.html:8
+#: dashboards/project/networks/templates/networks/subnets/_create.html:23
+#: dashboards/project/networks/templates/networks/subnets/create.html:3
+#: dashboards/project/networks/templates/networks/subnets/create.html:6
+msgid "Create Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:60
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:7
+#: dashboards/project/networks/subnets/tables.py:72
+#: dashboards/project/networks/templates/networks/subnets/_update.html:7
+msgid "Edit Subnet"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:72
+#: dashboards/project/access_and_security/security_groups/forms.py:91
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:15
+msgid "CIDR"
+msgstr "CIDR"
+
+#: dashboards/admin/networks/subnets/tables.py:73
+#: dashboards/project/networks/workflows.py:66
+#: dashboards/project/networks/subnets/forms.py:53
+#: dashboards/project/networks/subnets/tables.py:85
+msgid "IP Version"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/tables.py:74
+#: dashboards/project/networks/subnets/forms.py:54
+#: dashboards/project/networks/subnets/forms.py:104
+#: dashboards/project/networks/subnets/tables.py:86
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:19
+msgid "Gateway IP"
+msgstr ""
+
+#: dashboards/admin/networks/subnets/views.py:82
+#: dashboards/project/networks/subnets/views.py:86
+msgid "Unable to retrieve subnet details"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_create.html:18
+#: dashboards/project/networks/templates/networks/_create.html:17
+msgid "Select a name for your network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:16
+#: dashboards/admin/networks/templates/networks/ports/_update.html:21
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:25
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:17
+#: dashboards/project/instances/templates/instances/_update.html:16
+#: dashboards/project/networks/templates/networks/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_update.html:25
+#: dashboards/settings/ec2/templates/ec2/download_form.html:17
+#: dashboards/settings/project/templates/project/_openrc.html:24
+#: dashboards/settings/user/templates/user/_settings.html:17
+msgid "Description:"
+msgstr "说明:"
+
+#: dashboards/admin/networks/templates/networks/_update.html:17
+#: dashboards/project/networks/templates/networks/_update.html:17
+msgid "You may update the editable properties of your network here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/_update.html:22
+#: dashboards/admin/networks/templates/networks/ports/_update.html:27
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:31
+#: dashboards/project/instances/templates/instances/_update.html:22
+#: dashboards/project/networks/templates/networks/_update.html:22
+#: dashboards/project/networks/templates/networks/subnets/_update.html:31
+msgid "Save Changes"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/update.html:3
+#: dashboards/admin/networks/templates/networks/update.html:6
+#: dashboards/project/networks/templates/networks/update.html:3
+#: dashboards/project/networks/templates/networks/update.html:6
+msgid "Update Network"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_create.html:18
+msgid ""
+"You can create a port for the network. If you specify device ID to be "
+"attached, the device specified will be attached to the port created."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/_update.html:22
+msgid "You may update the editable properties of your port here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/ports/update.html:3
+#: dashboards/admin/networks/templates/networks/ports/update.html:6
+msgid "Update Port"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:18
+#: dashboards/project/networks/templates/networks/subnets/_create.html:18
+msgid ""
+"You can create a subnet for the network. Any network address can be "
+"specified unless the network address does not overlap other subnets in the "
+"network."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:14
+#: dashboards/project/networks/workflows.py:58
+#: dashboards/project/networks/subnets/forms.py:45
+#: dashboards/project/networks/subnets/tables.py:84
+#: dashboards/project/networks/templates/networks/subnets/_update.html:14
+msgid "Network Address"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:17
+#: dashboards/project/networks/templates/networks/subnets/_update.html:16
+msgid "IP version"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:26
+#: dashboards/project/networks/templates/networks/subnets/_update.html:26
+msgid "You may update the editable properties of your subnet here."
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/index.html:3
+#: dashboards/admin/networks/templates/networks/subnets/index.html:6
+#: dashboards/project/networks/templates/networks/detail.html:3
+msgid "Network Detail"
+msgstr ""
+
+#: dashboards/admin/networks/templates/networks/subnets/update.html:3
+#: dashboards/admin/networks/templates/networks/subnets/update.html:6
+#: dashboards/project/networks/templates/networks/subnets/update.html:3
+#: dashboards/project/networks/templates/networks/subnets/update.html:6
+msgid "Update Subnet"
+msgstr ""
+
+#: dashboards/admin/overview/templates/overview/usage.html:3
+msgid "Usage Overview"
+msgstr ""
+
+#: dashboards/admin/overview/templates/overview/usage.html:12
+msgid "Monitoring"
+msgstr ""
+
+#: dashboards/admin/projects/panel.py:29
+#: dashboards/admin/projects/tables.py:66
+#: dashboards/admin/projects/tables.py:95
+#: dashboards/admin/projects/templates/projects/index.html:8
+#: templates/403.html:24 templates/404.html:23 templates/500.html:23
+msgid "Projects"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:19
+msgid "Modify Users"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:32
+msgid "View Usage"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:39
+#: dashboards/admin/projects/templates/projects/_create.html:8
+#: dashboards/admin/projects/templates/projects/_create.html:23
+#: dashboards/admin/projects/templates/projects/create.html:6
+msgid "Create Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:46
+#: dashboards/admin/projects/workflows.py:269
+#: dashboards/admin/projects/templates/projects/update.html:3
+#: dashboards/admin/projects/templates/projects/update.html:6
+msgid "Edit Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:90
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:60
+#: dashboards/project/networks/templates/networks/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:15
+msgid "Project ID"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:91
+#: dashboards/admin/projects/workflows.py:76
+#: dashboards/admin/projects/workflows.py:251
+#: dashboards/admin/services/tables.py:42 dashboards/admin/users/tables.py:40
+#: dashboards/admin/users/tables.py:115
+msgid "Enabled"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:104
+msgid "Remove"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:105
+msgid "Removed"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:106 dashboards/admin/users/tables.py:41
+#: dashboards/admin/users/tables.py:75
+#: dashboards/project/instances/workflows.py:39
+msgid "User"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:107 dashboards/admin/users/panel.py:29
+#: dashboards/admin/users/tables.py:42 dashboards/admin/users/tables.py:76
+#: dashboards/admin/users/tables.py:122
+#: dashboards/admin/users/templates/users/index.html:8
+msgid "Users"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:125
+msgid "Unable to retrieve role information."
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:130
+msgid "Roles"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:134
+msgid "Users For Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:142
+msgid "Add To Project"
+msgstr ""
+
+#: dashboards/admin/projects/tables.py:154
+msgid "Add New Users"
+msgstr ""
+
+#: dashboards/admin/projects/views.py:67
+msgid "Unable to retrieve project information."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:87
+msgid "Unable to retrieve project list."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:110
+msgid "Unable to retrieve users."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:154
+msgid "Unable to retrieve default quota values."
+msgstr ""
+
+#: dashboards/admin/projects/views.py:182
+msgid "Unable to retrieve project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:37
+msgid "Injected File Content Bytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:38
+msgid "Metadata Items"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:41
+msgid "Injected Files"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:44
+#: dashboards/admin/volumes/panel.py:9 dashboards/admin/volumes/tables.py:15
+#: dashboards/admin/volumes/templates/volumes/index.html:3
+#: dashboards/admin/volumes/templates/volumes/index.html:6
+#: dashboards/project/volumes/panel.py:25
+#: dashboards/project/volumes/tables.py:38
+#: dashboards/project/volumes/tables.py:171
+#: dashboards/project/volumes/tables.py:183
+#: dashboards/project/volumes/templates/volumes/index.html:3
+#: dashboards/project/volumes/templates/volumes/index.html:6
+msgid "Volumes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:45
+msgid "Gigabytes"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:46
+msgid "RAM (MB)"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:47
+#: dashboards/project/access_and_security/floating_ips/tables.py:50
+#: dashboards/project/access_and_security/floating_ips/tables.py:128
+msgid "Floating IPs"
+msgstr "浮动IP"
+
+#: dashboards/admin/projects/workflows.py:50
+msgid "Quota"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:52
+msgid "From here you can set quotas (max limits) for the project."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:81
+#: dashboards/admin/projects/workflows.py:254
+msgid "Project Info"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:82
+#: dashboards/admin/projects/templates/projects/_create.html:18
+msgid "From here you can create a new project to organize users."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:101
+msgid "Unable to retrieve user list. Please try again later."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:155
+#: dashboards/admin/projects/templates/projects/_update_members.html:16
+msgid "Project Members"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:169
+#: dashboards/admin/users/views.py:47
+msgid "Unable to retrieve user list."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:180
+msgid "Add Project"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:181
+msgid "Finish"
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:182
+#, python-format
+msgid "Created new project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:183
+#, python-format
+msgid "Unable to create project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:227
+#, python-format
+msgid "Failed to add %s project members and set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:246
+msgid "Unable to set project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:256
+msgid "From here you can edit the project details."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:271
+#, python-format
+msgid "Modified project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:272
+#, python-format
+msgid "Unable to modify project \"%s\"."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:342
+#, python-format
+msgid "Failed to modify %s project members and update project quotas."
+msgstr ""
+
+#: dashboards/admin/projects/workflows.py:363
+msgid ""
+"Modified project information and members, but unable to modify project "
+"quotas."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:8
+#: dashboards/admin/projects/templates/projects/add_user.html:3
+#: dashboards/admin/projects/templates/projects/add_user.html:6
+msgid "Add User To Project"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:18
+msgid "Select the user role for the project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:23
+msgid "Add"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:7
+#, python-format
+msgid "Create User for project '%(tenant_name)s'."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:18
+msgid "From here you can create a new user to add to this project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:23
+#: dashboards/admin/users/tables.py:20
+#: dashboards/admin/users/templates/users/_create.html:7
+#: dashboards/admin/users/templates/users/_create.html:22
+#: dashboards/admin/users/templates/users/create.html:7
+msgid "Create User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:7
+#: dashboards/admin/projects/templates/projects/_quotas.html:22
+msgid "Update Quota"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:17
+#, python-format
+msgid ""
+"From here you can edit quotas (max limits) for the project %(tenant.name)s."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update.html:8
+#: dashboards/admin/projects/templates/projects/_update.html:23
+#: dashboards/admin/projects/templates/projects/quotas.html:6
+msgid "Update Project"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update.html:18
+msgid "From here you can edit a project."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:7
+msgid ""
+"From here you can add and remove members to this project from the list of "
+"all available users."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:10
+msgid "All Users"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:25
+#: dashboards/admin/projects/templates/projects/_update_members.html:32
+msgid "No users found."
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/create_user.html:3
+#: dashboards/admin/projects/templates/projects/create_user.html:6
+msgid "Add New User"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:3
+msgid "Project Usage Overview"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/usage.html:7
+msgid "Project Usage"
+msgstr ""
+
+#: dashboards/admin/projects/templates/projects/users.html:7
+msgid "Users for Project"
+msgstr ""
+
+#: dashboards/admin/quotas/panel.py:29 dashboards/admin/quotas/tables.py:36
+msgid "Quotas"
+msgstr ""
+
+#: dashboards/admin/quotas/tables.py:28
+msgid "Quota Name"
+msgstr ""
+
+#: dashboards/admin/quotas/tables.py:29
+msgid "Limit"
+msgstr ""
+
+#: dashboards/admin/quotas/views.py:46
+msgid "Unable to get quota info."
+msgstr ""
+
+#: dashboards/admin/quotas/templates/quotas/index.html:8
+msgid "Default Quotas"
+msgstr ""
+
+#: dashboards/admin/services/panel.py:29
+#: dashboards/admin/services/tables.py:47
+#: dashboards/admin/services/templates/services/index.html:8
+msgid "Services"
+msgstr ""
+
+#: dashboards/admin/services/tables.py:37
+msgid "Id"
+msgstr ""
+
+#: dashboards/admin/services/tables.py:39
+msgid "Service"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:54
+msgid "Passwords do not match."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:62 dashboards/admin/users/forms.py:115
+#: dashboards/admin/users/tables.py:108
+msgid "User Name"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:63 dashboards/admin/users/forms.py:116
+#: dashboards/admin/users/tables.py:109
+msgid "Email"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:65 dashboards/admin/users/forms.py:117
+msgid "Password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:70 dashboards/admin/users/forms.py:124
+msgid "Confirm Password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:73 dashboards/admin/users/forms.py:127
+msgid "Primary Project"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:75
+msgid "Role"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:96
+#, python-format
+msgid "User \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:106
+msgid "Unable to add userto primary project."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:110
+msgid "Unable to create user."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:151
+msgid "name"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:151
+msgid "email"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:160
+msgid "primary project"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:173
+#, python-format
+msgid "The user %s has no role defined for"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:181
+msgid "password"
+msgstr ""
+
+#: dashboards/admin/users/forms.py:190
+msgid "User has been updated successfully."
+msgstr ""
+
+#: dashboards/admin/users/forms.py:194
+#, python-format
+msgid "Unable to update %(attributes)s for the user."
+msgstr ""
+
+#: dashboards/admin/users/tables.py:32
+#: dashboards/project/images_and_snapshots/images/tables.py:68
+msgid "Edit"
+msgstr "编辑"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Enable"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:39
+msgid "Disable"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:40
+msgid "Disabled"
+msgstr ""
+
+#: dashboards/admin/users/tables.py:63
+msgid "You cannot disable the user you are currently logged in as."
+msgstr ""
+
+#: dashboards/admin/users/tables.py:114
+msgid "User ID"
+msgstr ""
+
+#: dashboards/admin/users/views.py:70
+msgid "Unable to update user."
+msgstr ""
+
+#: dashboards/admin/users/views.py:104
+msgid "Unable to retrieve user roles."
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_create.html:17
+msgid "From here you can create a new user and assign them to a project."
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_update.html:7
+#: dashboards/admin/users/templates/users/_update.html:22
+#: dashboards/admin/users/templates/users/update.html:7
+msgid "Update User"
+msgstr ""
+
+#: dashboards/admin/users/templates/users/_update.html:17
+msgid ""
+"From here you can edit the user's details, including their default project."
+msgstr ""
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:3
+#: dashboards/project/volumes/templates/volumes/detail.html:3
+msgid "Volume Details"
+msgstr ""
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:6
+#: dashboards/project/volumes/templates/volumes/detail.html:6
+msgid "Volume Detail"
+msgstr ""
+
+#: dashboards/project/dashboard.py:24
+msgid "Manage Compute"
+msgstr "管理计算"
+
+#: dashboards/project/dashboard.py:35
+msgid "Object Store"
+msgstr "块存储"
+
+#: dashboards/project/access_and_security/panel.py:26
+#: dashboards/project/instances/workflows.py:348
+msgid "Access & Security"
+msgstr "访问 & 安全"
+
+#: dashboards/project/access_and_security/views.py:51
+msgid "Unable to retrieve keypair list."
+msgstr "找不到密钥对列表。"
+
+#: dashboards/project/access_and_security/views.py:60
+#: dashboards/project/access_and_security/security_groups/views.py:74
+msgid "Unable to retrieve security groups."
+msgstr "找不到安全组"
+
+#: dashboards/project/access_and_security/views.py:69
+#: dashboards/project/access_and_security/floating_ips/workflows.py:49
+msgid "Unable to retrieve floating IP addresses."
+msgstr "找不到浮动IP。"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:32
+msgid "Pool"
+msgstr "资源池"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:43
+#, python-format
+msgid "Allocated Floating IP %(ip)s."
+msgstr "分配到的浮动IP %(ip)s。"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:47
+msgid "Unable to allocate Floating IP."
+msgstr "无法分配浮动IP。"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:37
+msgid "Allocate IP To Project"
+msgstr "分配IP给项目"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:47
+msgid "Release"
+msgstr "释放"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:48
+msgid "Released"
+msgstr "已释放"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:49
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:22
+msgid "Floating IP"
+msgstr "浮动IP"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:6
+#: dashboards/project/instances/tables.py:219
+msgid "Associate Floating IP"
+msgstr "绑定浮动IP"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:76
+msgid "Disassociate Floating IP"
+msgstr "解除浮动IP的绑定"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:90
+#, python-format
+msgid "Successfully disassociated Floating IP: %s"
+msgstr "浮动IP解除绑定成功: %s"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:94
+msgid "Unable to disassociate floating IP."
+msgstr "无法将浮动IP解除绑定"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:114
+#: dashboards/project/access_and_security/floating_ips/workflows.py:36
+#: dashboards/project/instances/tables.py:69
+#: dashboards/project/instances/tables.py:89
+#: dashboards/project/instances/tables.py:106
+#: dashboards/project/instances/tables.py:135
+#: dashboards/project/volumes/tables.py:206
+msgid "Instance"
+msgstr "实例"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:117
+msgid "Floating IP Pool"
+msgstr "浮动IP池"
+
+#: dashboards/project/access_and_security/floating_ips/views.py:65
+msgid "Unable to retrieve floating IP pools."
+msgstr "找不到浮动IP池"
+
+#: dashboards/project/access_and_security/floating_ips/views.py:68
+msgid "No floating IP pools available."
+msgstr "没有可用的浮动IP池"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:40
+msgid "Select the IP address you wish to associate with the selected instance."
+msgstr "请为选中的实例选择要绑定的IP地址"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:53
+msgid "Select an IP address"
+msgstr "选择一个IP地址"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:55
+msgid "No IP addresses available"
+msgstr "无效的IP地址"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:76
+#: dashboards/project/volumes/forms.py:160
+msgid "Select an instance"
+msgstr "请选择一个实例"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:78
+#: dashboards/project/volumes/forms.py:162
+msgid "No instances available"
+msgstr "无效的实例"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:97
+msgid "Manage Floating IP Associations"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:98
+msgid "Associate"
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:99
+#, python-format
+msgid "IP address %s associated."
+msgstr "IP地址 %s 已经被管理"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:100
+#, python-format
+msgid "Unable to associate IP address %s."
+msgstr ""
+
+#: dashboards/project/access_and_security/keypairs/forms.py:38
+#: dashboards/project/access_and_security/keypairs/forms.py:49
+#: dashboards/project/access_and_security/keypairs/tables.py:52
+msgid "Keypair Name"
+msgstr "密钥对名字"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:40
+msgid ""
+"Keypair names may only contain letters, numbers, underscores and hyphens."
+msgstr "密钥对名称只能包含字母,数字,下划线和连字符。"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:51
+msgid "Public Key"
+msgstr "公钥"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:60
+#, python-format
+msgid "Successfully imported public key: %s"
+msgstr "成功导入公钥:%s"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:65
+msgid "Unable to import keypair."
+msgstr "无法导入密钥对。"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:30
+#: dashboards/project/instances/tables.py:295
+#: dashboards/project/instances/workflows.py:335
+msgid "Keypair"
+msgstr "密钥对"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:31
+#: dashboards/project/access_and_security/keypairs/tables.py:60
+msgid "Keypairs"
+msgstr "密钥对"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:39
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html:6
+msgid "Import Keypair"
+msgstr "导入密钥对"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:46
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html:6
+msgid "Create Keypair"
+msgstr "创建密钥对"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:53
+msgid "Fingerprint"
+msgstr "指纹"
+
+#: dashboards/project/access_and_security/keypairs/views.py:74
+#, python-format
+msgid "Unable to create keypair: %(exc)s"
+msgstr "无法创建密钥对:%(exc)s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:46
+#, python-format
+msgid "Successfully created security group: %s"
+msgstr "安全组创建成功:%s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:52
+msgid "Unable to create security group."
+msgstr "安全组创建失败"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:57
+#: dashboards/project/access_and_security/security_groups/tables.py:93
+msgid "IP Protocol"
+msgstr "IP协议"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:61
+msgid "The protocol which this rule should be applied to."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:65
+#: dashboards/project/access_and_security/security_groups/forms.py:71
+#: dashboards/project/access_and_security/security_groups/tables.py:95
+msgid "From Port"
+msgstr "从端口"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:66
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP type in the range (-1: 255)"
+msgstr ""
+"TCP/UDP: 输入在1和65535之间的整数值。ICMP: 输入一个在(-1, 255)范围内的值给"
+"ICMP type"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:72
+#: dashboards/project/images_and_snapshots/images/tables.py:115
+msgid "Type"
+msgstr "类型"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:74
+#: dashboards/project/access_and_security/security_groups/forms.py:80
+#: dashboards/project/access_and_security/security_groups/tables.py:96
+msgid "To Port"
+msgstr "到端口"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:75
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP code in the range (-1: 255)"
+msgstr ""
+"TCP/UDP: 输入在1和65535之间的整数值。ICMP: 输入一个在(-1, 255)范围内的值给"
+"ICMP code"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:81
+msgid "Code"
+msgstr "编码"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:84
+msgid "Source Group"
+msgstr "源组"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:86
+msgid ""
+"To specify an allowed IP range, select CIDR. To allow access from all "
+"members of another security group select Source Group."
+msgstr ""
+
+#: dashboards/project/access_and_security/security_groups/forms.py:94
+msgid "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+msgstr "无类别域间路由(e.g. 192.168.0.0/24)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:121
+msgid "The ICMP type is invalid."
+msgstr "无效的ICMP类型。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:124
+msgid "The ICMP code is invalid."
+msgstr "无效的ICMP代码。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:127
+msgid "The ICMP type not in range (-1, 255)"
+msgstr "ICMP类型不在(-1, 255)范围内"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:130
+msgid "The ICMP code not in range (-1, 255)"
+msgstr "ICMP 代码不在(-1, 255)范围内 "
+
+#: dashboards/project/access_and_security/security_groups/forms.py:134
+msgid "The \"from\" port number is invalid."
+msgstr "\"从\"端口号不合法"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:137
+msgid "The \"to\" port number is invalid."
+msgstr "\"到\"端口号不合法"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:140
+msgid ""
+"The \"to\" port number must be greater than or equal to the \"from\" port "
+"number."
+msgstr "\"到\"端口号必须大于或者等于\"从\"端口号"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:146
+msgid "Either CIDR or Source Group may be specified, but not both."
+msgstr "可以指定CIDR或者源组,但不能同时使用"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:168
+#, python-format
+msgid "Successfully added rule: %s"
+msgstr "规则添加成功:%s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:173
+msgid "Unable to add rule to security group."
+msgstr "无法为安全组添加规则。"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:31
+msgid "Security Group"
+msgstr "安全组"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:32
+#: dashboards/project/access_and_security/security_groups/tables.py:66
+#: dashboards/project/instances/workflows.py:340
+#: dashboards/project/instances/templates/instances/_detail_overview.html:49
+msgid "Security Groups"
+msgstr "安全组"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:45
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html:6
+msgid "Create Security Group"
+msgstr "创建安全组"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:52
+msgid "Edit Rules"
+msgstr "编辑规则"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:72
+msgid "Rule"
+msgstr "规则"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:73
+msgid "Rules"
+msgstr "规则"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:97
+msgid "Source"
+msgstr "源"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:107
+msgid "Security Group Rules"
+msgstr "安全组规则"
+
+#: dashboards/project/access_and_security/security_groups/views.py:60
+msgid "Unable to retrieve security group."
+msgstr "无法检索到安全组。"
+
+#: dashboards/project/access_and_security/security_groups/views.py:80
+#, python-format
+msgid "%s (current)"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/index.html:6
+msgid "Access &amp; Security"
+msgstr "访问 &amp; 安全"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:8
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html:3
+msgid "Allocate Floating IP"
+msgstr "分配浮动IP"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:18
+msgid "Allocate a floating IP from a given floating ip pool."
+msgstr "从一个给定的浮动IP地址池分配一个浮动的IP。"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:20
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:19
+msgid "Project Quotas"
+msgstr "项目配额"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:31
+msgid "Allocate IP"
+msgstr "分配IP"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:17
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:17
+msgid ""
+"Keypairs are ssh credentials which are injected into images when they are "
+"launched. Creating a new key pair registers the public key and downloads the "
+"private key (a .pem file)."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:18
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:18
+msgid "Protect and use the key as you would any normal ssh private key."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:6
+msgid "Download Keypair"
+msgstr "下载密钥对"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:11
+#, python-format
+msgid ""
+"The keypair &quot;%(keypair_name)s&quot; should download automatically. If "
+"not use the link below."
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:15
+#, python-format
+msgid "Download keypair &quot;%(keypair_name)s&quot;"
+msgstr ""
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:18
+msgid "From here you can create a new security group"
+msgstr "点此创建新的安全组"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:9
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html:6
+msgid "Edit Security Group Rules"
+msgstr "编辑安全组的规则"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:12
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:19
+msgid "Add Rule"
+msgstr "添加规则"
+
+#: dashboards/project/containers/browsers.py:26
+msgid "Swift"
+msgstr "Swift"
+
+#: dashboards/project/containers/browsers.py:29
+#: dashboards/project/containers/tables.py:40
+msgid "Container"
+msgstr "容器"
+
+#: dashboards/project/containers/forms.py:39
+msgid "Slash is not an allowed character."
+msgstr "斜线是不允许的字符"
+
+#: dashboards/project/containers/forms.py:49
+#: dashboards/project/containers/tables.py:121
+msgid "Container Name"
+msgstr "容器名称"
+
+#: dashboards/project/containers/forms.py:57
+msgid "Container created successfully."
+msgstr "容器创建成功。"
+
+#: dashboards/project/containers/forms.py:68
+msgid "Folder created successfully."
+msgstr "目录创建成功"
+
+#: dashboards/project/containers/forms.py:71
+msgid "Unable to create container."
+msgstr "无法创建容器。"
+
+#: dashboards/project/containers/forms.py:79
+#: dashboards/project/containers/tables.py:253
+msgid "Object Name"
+msgstr "对象名称"
+
+#: dashboards/project/containers/forms.py:81
+msgid "File"
+msgstr "文件"
+
+#: dashboards/project/containers/forms.py:95
+msgid "Object was successfully uploaded."
+msgstr "对象上传成功。"
+
+#: dashboards/project/containers/forms.py:98
+msgid "Unable to upload object."
+msgstr "无法上传对象。"
+
+#: dashboards/project/containers/forms.py:102
+msgid "Destination container"
+msgstr "目标容器"
+
+#: dashboards/project/containers/forms.py:106
+msgid "Destination object name"
+msgstr "目标对象名称"
+
+#: dashboards/project/containers/forms.py:137
+#: dashboards/project/containers/forms.py:163
+msgid "Unable to copy object."
+msgstr "无法拷贝对象。"
+
+#: dashboards/project/containers/forms.py:153
+#, python-format
+msgid "Copied \"%(orig)s\" to \"%(dest)s\" as \"%(new)s\"."
+msgstr ""
+
+#: dashboards/project/containers/panel.py:29
+#: dashboards/project/containers/tables.py:41
+#: dashboards/project/containers/tables.py:128
+#: dashboards/project/containers/templates/containers/index.html:7
+msgid "Containers"
+msgstr "容器"
+
+#: dashboards/project/containers/tables.py:62
+#: dashboards/project/containers/templates/containers/_create.html:7
+#: dashboards/project/containers/templates/containers/_create.html:22
+#: dashboards/project/containers/templates/containers/create.html:6
+msgid "Create Container"
+msgstr "创建容器"
+
+#: dashboards/project/containers/tables.py:69
+msgid "View Container"
+msgstr "查看容器"
+
+#: dashboards/project/containers/tables.py:81
+#: dashboards/project/containers/templates/containers/_upload.html:23
+#: dashboards/project/containers/templates/containers/upload.html:3
+msgid "Upload Object"
+msgstr "上传对象"
+
+#: dashboards/project/containers/tables.py:137
+#: dashboards/project/containers/tables.py:156
+msgid "Object"
+msgstr "对象"
+
+#: dashboards/project/containers/tables.py:138
+#: dashboards/project/containers/tables.py:157
+#: dashboards/project/containers/tables.py:263
+msgid "Objects"
+msgstr "对象"
+
+#: dashboards/project/containers/tables.py:149
+msgid "Folder"
+msgstr "文件夹"
+
+#: dashboards/project/containers/tables.py:150
+msgid "Folders"
+msgstr "文件夹"
+
+#: dashboards/project/containers/tables.py:163
+msgid "Copy"
+msgstr "复制"
+
+#: dashboards/project/containers/tables.py:176
+msgid "Download"
+msgstr "下载"
+
+#: dashboards/project/containers/tables.py:232
+msgid "Create Folder"
+msgstr "创建文件夹"
+
+#: dashboards/project/containers/views.py:53
+msgid "Unable to retrieve container list."
+msgstr "无法检索容器列表"
+
+#: dashboards/project/containers/views.py:82
+msgid "Unable to retrieve object list."
+msgstr "找不到对象列表。"
+
+#: dashboards/project/containers/views.py:166
+msgid "Unable to retrieve object."
+msgstr "找不到对象。"
+
+#: dashboards/project/containers/views.py:200
+msgid "Unable to list containers."
+msgstr "找不到容器列表。"
+
+#: dashboards/project/containers/templates/containers/_copy.html:7
+#: dashboards/project/containers/templates/containers/_copy.html:22
+#: dashboards/project/containers/templates/containers/copy.html:3
+#: dashboards/project/containers/templates/containers/copy.html:6
+msgid "Copy Object"
+msgstr "复制对象"
+
+#: dashboards/project/containers/templates/containers/_copy.html:17
+msgid ""
+"Make a new copy of an existing object to store in this or another container. "
+"You may also specify a path at which the new copy should live inside of the "
+"selected container."
+msgstr ""
+"为现有对象创建一个新的副本,存储在这个或另外一个容器中。 您也可以在选中的容器"
+"中为新的副本指定存储路径 。"
+
+#: dashboards/project/containers/templates/containers/_create.html:17
+msgid ""
+"A container is a storage compartment for your data and provides a way for "
+"you to organize your data. You can think of a container as a folder in "
+"Windows &reg; or a directory in UNIX &reg;. The primary difference between a "
+"container and these other file system concepts is that containers cannot be "
+"nested. You can, however, create an unlimited number of containers within "
+"your account. Data must be stored in a container so you must have at least "
+"one container defined in your account prior to uploading data."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_upload.html:8
+msgid "Upload Object To Container"
+msgstr "上传对象到容器中"
+
+#: dashboards/project/containers/templates/containers/_upload.html:18
+msgid ""
+"An object is the basic storage entity and any optional metadata that "
+"represents the files you store in the OpenStack Object Storage system. When "
+"you upload data to OpenStack Object Storage, the data is stored as-is (no "
+"compression or encryption) and consists of a location (container), the "
+"object's name, and any metadata consisting of key/value pairs."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/upload.html:6
+msgid "Upload Objects"
+msgstr "上传对象"
+
+#: dashboards/project/images_and_snapshots/panel.py:26
+msgid "Images & Snapshots"
+msgstr "镜像 & 快照"
+
+#: dashboards/project/images_and_snapshots/views.py:63
+msgid "Unable to retrieve images."
+msgstr "找不到镜像。"
+
+#: dashboards/project/images_and_snapshots/views.py:74
+msgid "Unable to retrieve snapshots."
+msgstr "找不到快照。"
+
+#: dashboards/project/images_and_snapshots/views.py:82
+#: dashboards/project/volumes/forms.py:65
+msgid "Unable to retrieve volume snapshots."
+msgstr "找不到卷组快照。"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:42
+msgid "Image Location"
+msgstr "查找镜像"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:43
+msgid "An external (HTTP) URL to load the image from."
+msgstr "使用外部(HTTP)URL加载镜像。"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:46
+#: dashboards/project/images_and_snapshots/images/forms.py:130
+#: dashboards/project/images_and_snapshots/images/tables.py:126
+msgid "Format"
+msgstr "格式化"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:50
+msgid "AKI - Amazon Kernel Image"
+msgstr "AKI - 亚马逊内核镜像"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:53
+msgid "AMI - Amazon Machine Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:56
+msgid "ARI - Amazon Ramdisk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:59
+msgid "ISO - Optical Disk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:61
+msgid "QCOW2 - QEMU Emulator"
+msgstr "QCOW2 - QEMU 模拟器"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:68
+msgid "Minimum Disk (GB)"
+msgstr "最小磁盘(GB)"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:69
+#: dashboards/project/images_and_snapshots/images/forms.py:76
+msgid ""
+"The minimum disk size required to boot the image. If unspecified, this value "
+"defaults to 0 (no minimum)."
+msgstr "为启动镜像设置的最小磁盘。如果不指定, 默认值为零 (没有限制)。"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:75
+msgid "Minimum Ram (MB)"
+msgstr "最小内存(MB)"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:82
+#: dashboards/project/images_and_snapshots/images/forms.py:134
+#: dashboards/project/images_and_snapshots/images/tables.py:123
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:15
+msgid "Public"
+msgstr "公有"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:106
+#, python-format
+msgid "Your image %s has been queued for creation."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:110
+msgid "Unable to create new image."
+msgstr "无法创建新镜像"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:116
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:48
+msgid "Kernel ID"
+msgstr "内核ID"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:121
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:52
+msgid "Ramdisk ID"
+msgstr "内存ID"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:126
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:44
+msgid "Architecture"
+msgstr "架构"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:138
+#, python-format
+msgid "Unable to update image \"%s\"."
+msgstr "镜像更新失败 \"%s\"。"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:162
+msgid "Image was successfully updated."
+msgstr "镜像上传成功。"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:34
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:33
+#: dashboards/project/instances/workflows.py:455
+msgid "Launch"
+msgstr "运行"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:46
+#: dashboards/project/images_and_snapshots/images/tables.py:82
+#: dashboards/project/instances/workflows.py:168
+#: dashboards/project/instances/workflows.py:173
+msgid "Image"
+msgstr "镜像"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:61
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:31
+msgid "Create Image"
+msgstr "创建镜像"
+
+#: dashboards/project/images_and_snapshots/images/tabs.py:38
+msgid "Unable to retrieve image details."
+msgstr "无法检索到镜像细节。"
+
+#: dashboards/project/images_and_snapshots/images/views.py:61
+msgid "Unable to retrieve image."
+msgstr "无法检索到镜像。"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:37
+msgid "Instance ID"
+msgstr "实例ID"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:40
+#: dashboards/project/volumes/forms.py:193
+msgid "Snapshot Name"
+msgstr "快照名称"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:50
+#, python-format
+msgid "Snapshot \"%(name)s\" created for instance \"%(inst)s\""
+msgstr "实例 \"%(inst)s\" 的快照 \"%(name)s\" 已经建立"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:56
+msgid "Unable to create snapshot."
+msgstr "无法创建快照。"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:48
+#: dashboards/project/instances/workflows.py:107
+#: dashboards/project/instances/workflows.py:169
+msgid "Snapshot"
+msgstr "快照"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:49
+msgid "Snapshots"
+msgstr "快照"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:55
+msgid "Instance Snapshots"
+msgstr "实例快照"
+
+#: dashboards/project/images_and_snapshots/snapshots/views.py:53
+msgid "Unable to retrieve instance."
+msgstr "无法检索到实例。"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:6
+msgid "Images &amp; Snapshots"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:6
+msgid "Create An Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:18
+msgid "Specify an image to upload to the Image Service."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:21
+msgid ""
+"Currently only images available via an HTTP URL are supported. The image "
+"location must be accessible to the Image Service. Compressed image binaries "
+"are supported (.zip and .tar.gz.)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:24
+msgid "Please note: "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:25
+msgid ""
+"The Image Location field MUST be a valid and direct URL to the image binary. "
+"URLs that redirect or serve error pages will result in unusable images."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:3
+msgid "Image Overview"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:6
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:7
+#: dashboards/project/instances/templates/instances/_detail_overview.html:6
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:6
+msgid "Info"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:17
+msgid "Checksum"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:19
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:39
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:28
+msgid "Created"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:21
+msgid "Updated"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:27
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:34
+#: dashboards/project/instances/templates/instances/_detail_overview.html:19
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:23
+msgid "Specs"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:32
+msgid "Container Format"
+msgstr "容器格式"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:34
+msgid "Disk Format"
+msgstr "磁盘格式"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:40
+msgid "Custom Properties"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:56
+msgid "Euca2ools state"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:64
+msgid "Image Type"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html:4
+msgid "Image Detail "
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:8
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:3
+#: dashboards/project/instances/tables.py:179
+#: dashboards/project/volumes/tables.py:76
+msgid "Create Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:18
+msgid "Snapshots preserve the disk state of a running instance."
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:20
+#: dashboards/project/instances/workflows.py:75
+#: dashboards/project/instances/workflows.py:110
+#: dashboards/project/instances/templates/instances/_detail_overview.html:93
+#: dashboards/project/volumes/tables.py:37
+#: dashboards/project/volumes/tables.py:182
+msgid "Volume"
+msgstr "卷"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:38
+#: dashboards/project/instances/templates/instances/_detail_overview.html:29
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:27
+msgid "GB"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:6
+msgid "Create a Snapshot"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:3
+#, fuzzy
+msgid "Volume Snapshot Details"
+msgstr "卷快照"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:6
+#, fuzzy
+msgid "Volume Snapshot Detail"
+msgstr "卷快照"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:34
+#: dashboards/project/instances/workflows.py:76
+msgid "Volume Snapshot"
+msgstr "卷快照"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:35
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:85
+msgid "Volume Snapshots"
+msgstr "卷快照"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:43
+#: dashboards/project/volumes/tables.py:59
+#: dashboards/project/volumes/templates/volumes/_create.html:8
+#: dashboards/project/volumes/templates/volumes/_create.html:55
+msgid "Create Volume"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:80
+#: dashboards/project/volumes/forms.py:26
+msgid "Volume Name"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:41
+#, fuzzy
+msgid "Unable to retrieve snapshot details."
+msgstr "找不到快照。"
+
+#: dashboards/project/instances/forms.py:45
+#, python-format
+msgid "Instance \"%s\" updated."
+msgstr "实例 \"%s\" 已更新"
+
+#: dashboards/project/instances/forms.py:50
+msgid "Unable to update instance."
+msgstr "不能更新实例"
+
+#: dashboards/project/instances/tables.py:67
+msgid "Terminate"
+msgstr "终止"
+
+#: dashboards/project/instances/tables.py:68
+msgid "Scheduled termination of"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:87
+msgid "Reboot"
+msgstr "重启"
+
+#: dashboards/project/instances/tables.py:88
+msgid "Rebooted"
+msgstr "已重启"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Pause"
+msgstr "暂停"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Unpause"
+msgstr "取消暂停"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Paused"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:105
+msgid "Unpaused"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:133
+msgid "Suspend"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:133
+msgid "Resume"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:134
+msgid "Suspended"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:134
+msgid "Resumed"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:162
+#: dashboards/project/instances/workflows.py:454
+#: dashboards/project/instances/templates/instances/launch.html:3
+#: dashboards/project/instances/templates/instances/launch.html:6
+msgid "Launch Instance"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:169
+#: dashboards/project/instances/templates/instances/_update.html:7
+msgid "Edit Instance"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:189
+msgid "VNC Console"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:204
+msgid "View Log"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:252
+#, python-format
+msgid "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disk"
+msgstr ""
+
+#: dashboards/project/instances/tables.py:259
+#: dashboards/project/instances/tables.py:266
+msgid "Not available"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:36
+msgid "Log"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:48
+#: dashboards/project/instances/views.py:106
+#, python-format
+msgid "Unable to get log for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:55
+msgid "VNC"
+msgstr ""
+
+#: dashboards/project/instances/tabs.py:70
+#: dashboards/project/instances/views.py:122
+#, python-format
+msgid "Unable to get VNC console for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/views.py:59
+msgid "Unable to retrieve instances."
+msgstr "无法取得实例信息。"
+
+#: dashboards/project/instances/views.py:144
+msgid "Unable to retrieve instance details."
+msgstr ""
+
+#: dashboards/project/instances/views.py:179
+#, python-format
+msgid "Unable to retrieve details for instance \"%s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:53
+msgid "Project & User"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:66
+msgid "Don't boot from a volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:67
+msgid "Boot from volume."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:68
+msgid "Boot from volume snapshot (creates a new volume)."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:72
+#: dashboards/project/instances/workflows.py:90
+msgid "Volume Options"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:78
+#: dashboards/project/volumes/forms.py:126
+msgid "Device Name"
+msgstr "设备名称"
+
+#: dashboards/project/instances/workflows.py:81
+msgid "Volume mount point (e.g. 'vda' mounts at '/dev/vda')."
+msgstr "卷的挂接点 (例如:'vda' 挂接到 '/dev/vda' 上)."
+
+#: dashboards/project/instances/workflows.py:83
+msgid "Delete on Terminate"
+msgstr "在结束时删除"
+
+#: dashboards/project/instances/workflows.py:86
+msgid "Delete volume on instance terminate"
+msgstr "在实例结束后删除卷"
+
+#: dashboards/project/instances/workflows.py:100
+#, python-format
+msgid "Please choose a volume, or select %s."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:117
+msgid "Select Volume"
+msgstr "选择卷"
+
+#: dashboards/project/instances/workflows.py:125
+msgid "Unable to retrieve list of volumes."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:129
+msgid "Select Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:138
+msgid "Unable to retrieve list of volume snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:171
+msgid "Instance Source"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:174
+msgid "Instance Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:178
+msgid "Size of image to launch."
+msgstr "建立的映像大小"
+
+#: dashboards/project/instances/workflows.py:179
+msgid "Instance Count"
+msgstr "实例个数"
+
+#: dashboards/project/instances/workflows.py:182
+msgid "Number of instances to launch."
+msgstr "启动实例的个数"
+
+#: dashboards/project/instances/workflows.py:185
+msgid "Details"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:198
+msgid ""
+"There are no image sources available; you must first create an image before "
+"attempting to launch an instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:203
+msgid "Please select an option for the instance source."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:212
+msgid ""
+"Launching multiple instances is only supported for images and instance "
+"snapshots."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:229
+msgid "Unable to retrieve public images."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:244
+msgid "Unable to retrieve images for the current project."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:267
+msgid "Select Image"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:269
+msgid "No images available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:278
+msgid "Select Instance Snapshot"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:280
+msgid "No snapshots available."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:291
+msgid "Unable to retrieve instance flavors."
+msgstr "无法检索实例类型。"
+
+#: dashboards/project/instances/workflows.py:304 usage/base.py:114
+msgid "Unable to retrieve quota information."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:337
+msgid "Which keypair to use for authentication."
+msgstr "用于验证的密钥对。"
+
+#: dashboards/project/instances/workflows.py:344
+msgid "Launch instance in these security groups."
+msgstr "在这些安全组中启动实例。"
+
+#: dashboards/project/instances/workflows.py:349
+msgid ""
+"Control access to your instance via keypairs, security groups, and other "
+"mechanisms."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:359
+msgid "Unable to retrieve keypairs."
+msgstr "无法检索密钥对。"
+
+#: dashboards/project/instances/workflows.py:361
+msgid "Select a keypair"
+msgstr "选择一个密钥对"
+
+#: dashboards/project/instances/workflows.py:363
+msgid "No keypairs available."
+msgstr "无密钥对。"
+
+#: dashboards/project/instances/workflows.py:372
+msgid "Unable to retrieve list of security groups"
+msgstr "无法检索到安全组列表"
+
+#: dashboards/project/instances/workflows.py:392
+msgid "Customization Script"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:394
+msgid ""
+"A script or set of commands to be executed after the instance has been built "
+"(max 16kb)."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:401
+msgid "Post-Creation"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:415
+msgid "Launch instance withthese networks"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:419
+msgid "Networking"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:421
+msgid "Select networks for your instance."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:433
+msgid "Unable to retrieve networks."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:456
+#, python-format
+msgid "Launched %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:457
+#, python-format
+msgid "Unable to launch %(count)s named \"%(name)s\"."
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:470
+#, python-format
+msgid "%s instances"
+msgstr ""
+
+#: dashboards/project/instances/workflows.py:473
+msgid "instance"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:4
+msgid "Instance Console Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:7
+msgid "Log Length"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:9
+msgid "Go"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:11
+msgid "View Full Log"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:3
+msgid "Instance Overview"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:27
+msgid "VCPU"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:28
+#: usage/tables.py:20
+msgid "Disk"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:34
+msgid "IP Addresses"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:59
+msgid "No rules defined."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:68
+msgid "Meta"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:71
+msgid "Key Name"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:84
+msgid "Volumes Attached"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:88
+#: dashboards/project/volumes/tables.py:167
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:38
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:45
+msgid "Attached To"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:90
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:42
+msgid "on"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:94
+msgid "No volumes attached."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:3
+msgid "Instance VNC Console"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid ""
+"If VNC console is not responding to keyboard input: click the grey status "
+"bar below."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid "Click here to show only VNC"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:8
+msgid "VNC console is currently unavailabe. Please try again later."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:9
+msgid "Reload"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:2
+msgid ""
+"You can customize your instance after it's launched using the options "
+"available here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:3
+msgid ""
+"The \"Customization Script\" field is analogous to \"User Data\" in other "
+"systems."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:3
+msgid "Specify the details for launching an instance."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:4
+msgid ""
+"The chart below shows the resources used by this project in relation to the "
+"project's quotas."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:6
+msgid "Flavor Details"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+msgid "Total Disk"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "MB"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:21
+msgid "Number of Instances"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:29
+msgid "Number of VCPUs"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "Total RAM"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_volumes_help.html:3
+msgid ""
+"An instance can be launched with varying types of attached storage. You may "
+"select from those options here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_update.html:17
+msgid "You may update the editable properties of your instance here."
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/detail.html:3
+msgid "Instance Detail"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/update.html:3
+#: dashboards/project/instances/templates/instances/update.html:6
+msgid "Update Instance"
+msgstr ""
+
+#: dashboards/project/networks/tables.py:81
+msgid "Add Subnet"
+msgstr ""
+
+#: dashboards/project/networks/views.py:86
+msgid "Unable to retrieve network details."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:37
+msgid "Network Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:42
+msgid ""
+"From here you can create a new network.\n"
+"In addition a subnet associated with the network can be created in the next "
+"panel."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:56
+msgid "Subnet Name (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:61
+#: dashboards/project/networks/subnets/forms.py:48
+msgid "Network address in CIDR format (e.g. 192.168.0.0/24)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:67
+msgid "Gateway IP (optional)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:70
+#: dashboards/project/networks/subnets/forms.py:57
+#: dashboards/project/networks/subnets/forms.py:107
+msgid "IP address of Gateway (e.g. 192.168.0.1)"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:77
+msgid ""
+"You can create a subnet associated with the new network, in which case "
+"\"Network Address\" must be specified. If you wish to create a network "
+"WITHOUT a subnet, uncheck the \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:89
+msgid "Specify \"Network Address\" or clear \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:94
+#: dashboards/project/networks/subnets/forms.py:70
+msgid "Network Address and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:98
+#: dashboards/project/networks/subnets/forms.py:74
+#: dashboards/project/networks/subnets/forms.py:119
+msgid "Gateway IP and IP version are inconsistent."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:112
+msgid "Create"
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:113
+#, python-format
+msgid "Created network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:114
+#, python-format
+msgid "Unable to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:130
+#, python-format
+msgid "Network \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:133
+#, python-format
+msgid "Failed to create network \"%s\"."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:152
+#, python-format
+msgid "Subnet \"%s\" was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:155
+#, python-format
+msgid "Failed to create subnet \"%(sub)s\" for network \"%(net)s\"."
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Attached"
+msgstr ""
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Detached"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:85
+#, python-format
+msgid "Subnet %s was successfully created."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:90
+#, python-format
+msgid "Failed to create subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:131
+#, python-format
+msgid "Subnet %s was successfully updated."
+msgstr ""
+
+#: dashboards/project/networks/subnets/forms.py:136
+#, python-format
+msgid "Failed to update subnet %s"
+msgstr ""
+
+#: dashboards/project/networks/subnets/tabs.py:42
+msgid "Unable to retrieve subnet details."
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/_detail_overview.html:3
+msgid "Network Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/detail.html:6
+msgid "Network Detail: "
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:3
+msgid "Port Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:17
+msgid "Fixed IP"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:21
+msgid "IP address:"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:22
+msgid "Subnet ID"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:28
+msgid "Mac Address"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/ports/detail.html:3
+#: dashboards/project/networks/templates/networks/ports/detail.html:6
+msgid "Port Detail"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:3
+msgid "Subnet Overview"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:21
+msgid "IP allocation pool"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:24
+msgid "Start"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:25
+msgid " - End"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/detail.html:3
+#: dashboards/project/networks/templates/networks/subnets/detail.html:6
+msgid "Subnet Detail"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:29
+msgid "Size (GB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:30
+msgid "Use snapshot as a source"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:49
+#, python-format
+msgid "Volume size must be equal to or greater than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:54
+msgid "Unable to load the specified snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:59
+msgid "Choose a snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:83
+#, python-format
+msgid "The volume size cannot be less than the snapshot size (%sGB)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:92
+#, python-format
+msgid ""
+"A volume of %(req)iGB cannot be created as you only have %(avail)iGB of your "
+"quota available."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:99
+msgid "You are already using all of your available volumes."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:115
+msgid "Unable to create volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:123
+msgid "Attach to Instance"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:124
+msgid "Select an instance to attach to."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:168
+msgid "Unknown instance (None)"
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:179
+#, python-format
+msgid "Attaching volume %(vol)s to instance %(inst)s on %(dev)s."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:188
+msgid "Unable to attach volume."
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:212
+#, python-format
+msgid "Creating volume snapshot \"%s\""
+msgstr ""
+
+#: dashboards/project/volumes/forms.py:218
+msgid "Unable to create volume snapshot."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:46
+#, fuzzy, python-format
+msgid "Unable to delete volume \"%s\". One or more snapshots depend on it."
+msgstr "找不到卷组快照。"
+
+#: dashboards/project/volumes/tables.py:66
+msgid "Edit Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:93
+#, python-format
+msgid "%sGB"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:106
+#: dashboards/project/volumes/views.py:149
+msgid "Unable to retrieve attachment information."
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:123
+#, python-format
+msgid "Attached to %(instance)s on %(dev)s"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:180
+msgid "Detach"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:181
+msgid "Detaching"
+msgstr ""
+
+#: dashboards/project/volumes/tables.py:216
+#, python-format
+msgid "%(dev)s on instance %(instance_name)s"
+msgstr ""
+
+#: dashboards/project/volumes/tabs.py:42
+msgid "Unable to retrieve volume details."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:50
+msgid "Unable to retrieve volume list."
+msgstr ""
+
+#: dashboards/project/volumes/views.py:58
+msgid "Unable to retrieve volume/instance attachment information"
+msgstr ""
+
+#: dashboards/project/volumes/views.py:130
+#: dashboards/project/volumes/views.py:140
+msgid "Unable to retrieve volume information."
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:9
+#: dashboards/project/volumes/templates/volumes/attach.html:6
+msgid "Manage Volume Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:13
+msgid "Attach To Instance"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:22
+msgid "Attach Volume"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:20
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:18
+msgid "Volumes are block devices that can be attached to instances."
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:22
+msgid "Volume Quotas"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:25
+msgid "Total Gigabytes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create.html:34
+msgid "Number of Volumes"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:8
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:23
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:3
+msgid "Create Volume Snapshot"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:3
+msgid "Volume Overview"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:34
+msgid "Attachments"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:46
+msgid "Not attached"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/create.html:6
+msgid "Create a Volume"
+msgstr ""
+
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:6
+msgid "Create a Volume Snapshot"
+msgstr ""
+
+#: dashboards/settings/dashboard.py:24 templates/_header.html:4
+msgid "Settings"
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:36 dashboards/settings/project/forms.py:36
+msgid "Select a Project"
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:46
+msgid "Unable to retrieve tenant list."
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:88
+msgid "Unable to fetch EC2 credentials."
+msgstr ""
+
+#: dashboards/settings/ec2/forms.py:101
+#, python-format
+msgid "Error writing zipfile: %(exc)s"
+msgstr ""
+
+#: dashboards/settings/ec2/panel.py:25
+msgid "EC2 Credentials"
+msgstr ""
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:8
+#: dashboards/settings/ec2/templates/ec2/download_form.html:23
+#: dashboards/settings/ec2/templates/ec2/index.html:3
+#: dashboards/settings/ec2/templates/ec2/index.html:6
+msgid "Download EC2 Credentials"
+msgstr ""
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:18
+msgid ""
+"Clicking \"Download EC2 Credentials\" will download a zip file which "
+"includes an rc file with your access/secret keys, as well as your x509 "
+"private key and certificate."
+msgstr ""
+
+#: dashboards/settings/project/forms.py:71
+#, python-format
+msgid "Error Downloading RC File: %s"
+msgstr ""
+
+#: dashboards/settings/project/panel.py:25
+#: dashboards/settings/project/templates/project/_openrc.html:8
+#: dashboards/settings/project/templates/project/settings.html:3
+#: dashboards/settings/project/templates/project/settings.html:6
+msgid "OpenStack API"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:27
+msgid "Service Name"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:29
+msgid "Service Endpoint"
+msgstr ""
+
+#: dashboards/settings/project/tables.py:33
+msgid "API Endpoints"
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:15
+msgid "Download OpenStack RC File"
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:25
+msgid ""
+"Download the RC file for the selected project, then type \"source openrc\" "
+"in the terminal to configure your environment to communicate with OpenStack."
+msgstr ""
+
+#: dashboards/settings/project/templates/project/_openrc.html:30
+msgid "Download RC File"
+msgstr ""
+
+#: dashboards/settings/user/forms.py:57
+msgid "Settings saved."
+msgstr ""
+
+#: dashboards/settings/user/panel.py:25
+#: dashboards/settings/user/templates/user/_settings.html:8
+#: dashboards/settings/user/templates/user/settings.html:3
+#: dashboards/settings/user/templates/user/settings.html:6
+msgid "User Settings"
+msgstr ""
+
+#: dashboards/settings/user/templates/user/_settings.html:18
+msgid "From here you can modify dashboard settings for your user."
+msgstr ""
+
#: templates/403.html:4 templates/403.html.py:9
msgid "Forbidden"
msgstr "禁止"
@@ -84,10 +3240,6 @@ msgstr "禁止"
msgid "Home"
msgstr "主页"
-#: templates/403.html:24 templates/404.html:23 templates/500.html:23
-msgid "Projects"
-msgstr "项目"
-
#: templates/404.html:4
msgid "Page Not Found"
msgstr "页面未找到"
@@ -109,3 +3261,47 @@ msgid ""
"An unexpected error occurred while processing your request. Please try your "
"request again."
msgstr "处理你的请求时发生了意想不到的错误。请重试。"
+
+#: templates/_header.html:3
+msgid "Logged in as"
+msgstr ""
+
+#: templates/_header.html:6
+msgid "Help"
+msgstr ""
+
+#: templates/_header.html:8
+msgid "Sign Out"
+msgstr ""
+
+#: test/settings.py:50
+msgid "Password must be between 8 and 18 characters."
+msgstr ""
+
+#: usage/base.py:97
+msgid "Unable to retrieve usage information."
+msgstr ""
+
+#: usage/base.py:100
+msgid "You are viewing data for the future, which may or may not exist."
+msgstr ""
+
+#: usage/tables.py:11
+msgid "Download CSV Summary"
+msgstr ""
+
+#: usage/tables.py:25
+msgid "VCPU Hours"
+msgstr ""
+
+#: usage/tables.py:32
+msgid "Disk GB Hours"
+msgstr ""
+
+#: usage/tables.py:40 usage/tables.py:68
+msgid "Usage Summary"
+msgstr ""
+
+#: usage/tables.py:60
+msgid "Uptime"
+msgstr ""
diff --git a/openstack_dashboard/locale/zh_TW/LC_MESSAGES/django.mo b/openstack_dashboard/locale/zh_TW/LC_MESSAGES/django.mo
index c1e5b2806..764c2b7c6 100644
--- a/openstack_dashboard/locale/zh_TW/LC_MESSAGES/django.mo
+++ b/openstack_dashboard/locale/zh_TW/LC_MESSAGES/django.mo
Binary files differ
diff --git a/openstack_dashboard/locale/zh_TW/LC_MESSAGES/django.po b/openstack_dashboard/locale/zh_TW/LC_MESSAGES/django.po
index d1546a927..339c414a9 100644
--- a/openstack_dashboard/locale/zh_TW/LC_MESSAGES/django.po
+++ b/openstack_dashboard/locale/zh_TW/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Horizon\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-09-18 22:18+0000\n"
+"POT-Creation-Date: 2012-10-05 19:30+0000\n"
"PO-Revision-Date: 2012-08-16 01:59+0000\n"
"Last-Translator: Chao-Hsiung Liao <pesder@gmail.com>\n"
"Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/"
@@ -19,63 +19,3242 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-#: settings.py:141
+#: settings.py:142
msgid "Bulgarian (Bulgaria)"
msgstr ""
-#: settings.py:142
+#: settings.py:143
msgid "Czech"
msgstr ""
-#: settings.py:143
+#: settings.py:144
msgid "English"
msgstr "英文"
-#: settings.py:144
+#: settings.py:145
msgid "Spanish"
msgstr "西班牙文"
-#: settings.py:145
+#: settings.py:146
msgid "French"
msgstr "法文"
-#: settings.py:146
+#: settings.py:147
msgid "Italiano"
msgstr "義大利文"
-#: settings.py:147
+#: settings.py:148
msgid "Japanese"
msgstr "日文"
-#: settings.py:148
+#: settings.py:149
msgid "Korean (Korea)"
msgstr ""
-#: settings.py:149
+#: settings.py:150
msgid "Dutch (Netherlands)"
msgstr ""
-#: settings.py:150
+#: settings.py:151
msgid "Polish"
msgstr "波蘭文"
-#: settings.py:151
+#: settings.py:152
msgid "Portuguese"
msgstr "葡萄牙文"
-#: settings.py:152
+#: settings.py:153
#, fuzzy
msgid "Portuguese (Brazil)"
msgstr "葡萄牙文"
-#: settings.py:153
+#: settings.py:154
msgid "Simplified Chinese"
msgstr "簡體中文"
-#: settings.py:154
+#: settings.py:155
msgid "Traditional Chinese"
msgstr "繁體中文"
+#: api/keystone.py:56
+#, python-format
+msgid "%(type)s (%(backend)s backend)"
+msgstr "%(type)s (%(backend)s 後端)"
+
+#: api/nova.py:191
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(group)s"
+msgstr "允许 %(from)s:%(to)s 從群組%(group)s的連線"
+
+#: api/nova.py:196
+#, python-format
+msgid "ALLOW %(from)s:%(to)s from %(cidr)s"
+msgstr "允许 %(from)s:%(to)s 從網段%(cidr)s的連線"
+
+#: api/nova.py:532
+msgid "Unknown instance"
+msgstr "不明的個體"
+
+#: api/swift.py:217
+msgid "Unicode is not currently supported for object copy."
+msgstr "目前並不支援Unicode的物件複製。"
+
+#: dashboards/admin/dashboard.py:24
+msgid "System Panel"
+msgstr "系統面板"
+
+#: dashboards/admin/dashboard.py:30
+msgid "Admin"
+msgstr "管理者"
+
+#: dashboards/admin/flavors/forms.py:36 dashboards/admin/networks/forms.py:34
+#: dashboards/admin/networks/forms.py:69
+#: dashboards/admin/networks/ports/forms.py:40
+#: dashboards/admin/networks/ports/forms.py:72
+#: dashboards/admin/networks/ports/tables.py:73
+#: dashboards/admin/networks/subnets/tables.py:70
+#: dashboards/admin/projects/tables.py:87
+#: dashboards/admin/projects/workflows.py:71
+#: dashboards/admin/services/tables.py:38
+#: dashboards/admin/volumes/tables.py:10
+#: dashboards/project/access_and_security/security_groups/forms.py:36
+#: dashboards/project/access_and_security/security_groups/tables.py:58
+#: dashboards/project/images_and_snapshots/images/forms.py:40
+#: dashboards/project/images_and_snapshots/images/forms.py:115
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:9
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:10
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:77
+#: dashboards/project/instances/templates/instances/_detail_overview.html:9
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:9
+#: dashboards/project/networks/forms.py:37
+#: dashboards/project/networks/tables.py:94
+#: dashboards/project/networks/ports/tables.py:40
+#: dashboards/project/networks/subnets/forms.py:43
+#: dashboards/project/networks/subnets/forms.py:102
+#: dashboards/project/networks/subnets/tables.py:82
+#: dashboards/project/networks/templates/networks/_detail_overview.html:7
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:9
+#: dashboards/project/volumes/tables.py:144
+#: dashboards/project/volumes/tables.py:164
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:9
+msgid "Name"
+msgstr "名稱"
+
+#: dashboards/admin/flavors/forms.py:37 dashboards/admin/flavors/tables.py:41
+#: dashboards/admin/projects/workflows.py:39
+#: dashboards/project/instances/templates/instances/_detail_overview.html:26
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:10
+#: usage/tables.py:19
+msgid "VCPUs"
+msgstr "虛擬處理器"
+
+#: dashboards/admin/flavors/forms.py:38
+#, fuzzy
+msgid "RAM MB"
+msgstr "RAM (MB)"
+
+#: dashboards/admin/flavors/forms.py:39
+msgid "Root Disk GB"
+msgstr "主磁碟 GB"
+
+#: dashboards/admin/flavors/forms.py:40
+msgid "Ephemeral Disk GB"
+msgstr "暫用磁碟 GB"
+
+#: dashboards/admin/flavors/forms.py:50
+msgid "Unable to get unique ID for new flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:67
+#, python-format
+msgid "Created flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:71
+msgid "Unable to create flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:92
+#, python-format
+msgid "Updated flavor \"%s\"."
+msgstr ""
+
+#: dashboards/admin/flavors/forms.py:96
+msgid "Unable to update flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/panel.py:29 dashboards/admin/flavors/tables.py:15
+#: dashboards/admin/flavors/tables.py:52
+#: dashboards/admin/flavors/templates/flavors/index.html:3
+#: dashboards/admin/flavors/templates/flavors/index.html:6
+msgid "Flavors"
+msgstr "規格"
+
+#: dashboards/admin/flavors/tables.py:14
+#: dashboards/project/instances/workflows.py:177
+#: dashboards/project/instances/templates/instances/_detail_overview.html:22
+msgid "Flavor"
+msgstr "規格"
+
+#: dashboards/admin/flavors/tables.py:23
+#: dashboards/admin/flavors/templates/flavors/_create.html:8
+#: dashboards/admin/flavors/templates/flavors/_create.html:23
+#: dashboards/admin/flavors/templates/flavors/create.html:3
+#: dashboards/admin/flavors/templates/flavors/create.html:6
+msgid "Create Flavor"
+msgstr "建立規格"
+
+#: dashboards/admin/flavors/tables.py:30
+#: dashboards/admin/flavors/templates/flavors/_edit.html:8
+#: dashboards/admin/flavors/templates/flavors/edit.html:3
+#: dashboards/admin/flavors/templates/flavors/edit.html:6
+msgid "Edit Flavor"
+msgstr ""
+
+#: dashboards/admin/flavors/tables.py:36
+#, python-format
+msgid "%sMB"
+msgstr "%sMB"
+
+#: dashboards/admin/flavors/tables.py:40
+msgid "Flavor Name"
+msgstr "規格名稱"
+
+#: dashboards/admin/flavors/tables.py:43
+#: dashboards/project/instances/templates/instances/_detail_overview.html:24
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: usage/tables.py:22
+msgid "RAM"
+msgstr "記憶體"
+
+#: dashboards/admin/flavors/tables.py:45
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+msgid "Root Disk"
+msgstr "主磁碟"
+
+#: dashboards/admin/flavors/tables.py:47
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+msgid "Ephemeral Disk"
+msgstr "暫用磁碟"
+
+#: dashboards/admin/flavors/views.py:49
+msgid "Unable to retrieve flavor list."
+msgstr ""
+
+#: dashboards/admin/flavors/views.py:76
+msgid "Unable to retrieve flavor data."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:17
+#: dashboards/admin/flavors/templates/flavors/_edit.html:17
+#: dashboards/admin/images/templates/images/_update.html:17
+#: dashboards/admin/networks/templates/networks/_create.html:17
+#: dashboards/admin/networks/templates/networks/ports/_create.html:17
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:17
+#: dashboards/admin/projects/tables.py:89
+#: dashboards/admin/projects/workflows.py:74
+#: dashboards/admin/projects/templates/projects/_add_user.html:17
+#: dashboards/admin/projects/templates/projects/_create.html:17
+#: dashboards/admin/projects/templates/projects/_create_user.html:17
+#: dashboards/admin/projects/templates/projects/_quotas.html:16
+#: dashboards/admin/projects/templates/projects/_update.html:17
+#: dashboards/admin/users/templates/users/_create.html:16
+#: dashboards/admin/users/templates/users/_update.html:16
+#: dashboards/project/access_and_security/security_groups/forms.py:38
+#: dashboards/project/access_and_security/security_groups/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:16
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:17
+#: dashboards/project/containers/templates/containers/_copy.html:16
+#: dashboards/project/containers/templates/containers/_create.html:16
+#: dashboards/project/containers/templates/containers/_upload.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/_create.html:16
+#: dashboards/project/networks/templates/networks/subnets/_create.html:17
+#: dashboards/project/volumes/forms.py:28
+#: dashboards/project/volumes/forms.py:195
+#: dashboards/project/volumes/tables.py:147
+#: dashboards/project/volumes/templates/volumes/_create.html:18
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:17
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:14
+msgid "Description"
+msgstr "敘述"
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:18
+msgid "From here you can define the sizing of a new flavor."
+msgstr "您可以在這裡制定新規格的配置"
+
+#: dashboards/admin/flavors/templates/flavors/_create.html:24
+#: dashboards/admin/flavors/templates/flavors/_edit.html:25
+#: dashboards/admin/images/templates/images/_update.html:24
+#: dashboards/admin/networks/templates/networks/_create.html:24
+#: dashboards/admin/networks/templates/networks/_update.html:23
+#: dashboards/admin/networks/templates/networks/ports/_create.html:24
+#: dashboards/admin/networks/templates/networks/ports/_update.html:28
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:24
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:32
+#: dashboards/admin/projects/templates/projects/_add_user.html:24
+#: dashboards/admin/projects/templates/projects/_create.html:24
+#: dashboards/admin/projects/templates/projects/_create_user.html:24
+#: dashboards/admin/projects/templates/projects/_quotas.html:23
+#: dashboards/admin/projects/templates/projects/_update.html:24
+#: dashboards/admin/users/templates/users/_create.html:23
+#: dashboards/admin/users/templates/users/_update.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:32
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:24
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:20
+#: dashboards/project/containers/templates/containers/_copy.html:23
+#: dashboards/project/containers/templates/containers/_create.html:23
+#: dashboards/project/containers/templates/containers/_upload.html:24
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:32
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:24
+#: dashboards/project/instances/templates/instances/_update.html:23
+#: dashboards/project/networks/templates/networks/_create.html:23
+#: dashboards/project/networks/templates/networks/_update.html:23
+#: dashboards/project/networks/templates/networks/subnets/_create.html:24
+#: dashboards/project/networks/templates/networks/subnets/_update.html:32
+#: dashboards/project/volumes/templates/volumes/_attach.html:24
+#: dashboards/project/volumes/templates/volumes/_create.html:56
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:24
+#: dashboards/settings/ec2/templates/ec2/download_form.html:24
+#: dashboards/settings/project/templates/project/_openrc.html:31
+#: dashboards/settings/user/templates/user/_settings.html:24
+msgid "Cancel"
+msgstr "取消"
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:18
+msgid "From here you can alter the sizing of the current flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:19
+msgid ""
+"Note: this will not affect the resources allocated to any existing instances "
+"using this flavor."
+msgstr ""
+
+#: dashboards/admin/flavors/templates/flavors/_edit.html:24
+#: dashboards/admin/projects/workflows.py:270
+#: dashboards/settings/user/templates/user/_settings.html:23
+msgid "Save"
+msgstr "儲存"
+
+#: dashboards/admin/images/panel.py:29 dashboards/admin/images/tables.py:44
+#: dashboards/admin/images/templates/images/index.html:3
+#: dashboards/admin/images/templates/images/index.html:6
+#: dashboards/project/images_and_snapshots/images/tables.py:47
+#: dashboards/project/images_and_snapshots/images/tables.py:132
+msgid "Images"
+msgstr "映像"
+
+#: dashboards/admin/images/tables.py:40
+#: dashboards/project/images_and_snapshots/images/tables.py:113
+#: dashboards/project/instances/templates/instances/_detail_overview.html:74
+msgid "Image Name"
+msgstr "映像名稱"
+
+#: dashboards/admin/images/views.py:55
+msgid "Unable to retrieve image list."
+msgstr "無法取得映像列表"
+
+#: dashboards/admin/images/templates/images/_update.html:8
+#: dashboards/admin/images/templates/images/_update.html:23
+#: dashboards/admin/images/templates/images/update.html:4
+#: dashboards/admin/images/templates/images/update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:22
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/update.html:6
+msgid "Update Image"
+msgstr "更新映像"
+
+#: dashboards/admin/images/templates/images/_update.html:18
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:17
+msgid "From here you can modify different properties of an image."
+msgstr "您可以在這裡修改映像的各個屬性內容"
+
+#: dashboards/admin/instances/panel.py:29
+#: dashboards/admin/instances/tables.py:94
+#: dashboards/admin/instances/templates/instances/index.html:3
+#: dashboards/admin/projects/workflows.py:40
+#: dashboards/project/instances/panel.py:25
+#: dashboards/project/instances/tables.py:70
+#: dashboards/project/instances/tables.py:90
+#: dashboards/project/instances/tables.py:107
+#: dashboards/project/instances/tables.py:136
+#: dashboards/project/instances/tables.py:313
+#: dashboards/project/instances/templates/instances/index.html:3
+#: dashboards/project/instances/templates/instances/index.html:6
+msgid "Instances"
+msgstr "執行個體"
+
+#: dashboards/admin/instances/tables.py:60 usage/tables.py:30
+msgid "Project Name"
+msgstr "專案名稱"
+
+#: dashboards/admin/instances/tables.py:67
+#: dashboards/admin/services/tables.py:40
+msgid "Host"
+msgstr "主機"
+
+#: dashboards/admin/instances/tables.py:71
+#: dashboards/project/instances/tables.py:290
+#: dashboards/project/instances/workflows.py:176 usage/tables.py:57
+msgid "Instance Name"
+msgstr "執行個體名稱"
+
+#: dashboards/admin/instances/tables.py:72
+#: dashboards/project/access_and_security/floating_ips/tables.py:111
+#: dashboards/project/access_and_security/floating_ips/workflows.py:32
+#: dashboards/project/access_and_security/floating_ips/workflows.py:39
+#: dashboards/project/instances/tables.py:291
+msgid "IP Address"
+msgstr "IP位址"
+
+#: dashboards/admin/instances/tables.py:74
+#: dashboards/project/containers/tables.py:256
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:30
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:37
+#: dashboards/project/instances/tables.py:293
+#: dashboards/project/volumes/tables.py:150
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:26
+msgid "Size"
+msgstr "大小"
+
+#: dashboards/admin/instances/tables.py:79
+#: dashboards/admin/networks/tables.py:74
+#: dashboards/admin/networks/ports/tables.py:77
+#: dashboards/project/images_and_snapshots/images/tables.py:119
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:13
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:18
+#: dashboards/project/instances/tables.py:298
+#: dashboards/project/instances/templates/instances/_detail_overview.html:13
+#: dashboards/project/networks/tables.py:100
+#: dashboards/project/networks/ports/tables.py:44
+#: dashboards/project/networks/templates/networks/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:30
+#: dashboards/project/volumes/tables.py:154
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:17
+msgid "Status"
+msgstr "狀態"
+
+#: dashboards/admin/instances/tables.py:83
+#: dashboards/project/instances/tables.py:302
+msgid "Task"
+msgstr "工作"
+
+#: dashboards/admin/instances/tables.py:90
+#: dashboards/project/instances/tables.py:309
+msgid "Power State"
+msgstr "電源狀態"
+
+#: dashboards/admin/instances/views.py:49
+#: dashboards/project/access_and_security/views.py:76
+#: dashboards/project/access_and_security/floating_ips/workflows.py:65
+msgid "Unable to retrieve instance list."
+msgstr "無法取得執行個體列表"
+
+#: dashboards/admin/instances/views.py:63
+#: dashboards/admin/networks/views.py:48
+msgid "Unable to retrieve instance tenant information."
+msgstr "無法取得執行個體的專案資訊"
+
+#: dashboards/admin/instances/views.py:80
+#: dashboards/project/instances/views.py:82
+msgid "Unable to retrieve instance size information."
+msgstr "無法取得執行個體大小資訊"
+
+#: dashboards/admin/instances/templates/instances/index.html:6
+msgid "All Instances"
+msgstr "所有執行個體"
+
+#: dashboards/admin/networks/forms.py:36
+#: dashboards/admin/networks/tables.py:67
+#: dashboards/admin/projects/tables.py:65 dashboards/project/dashboard.py:40
+#: dashboards/project/instances/workflows.py:38
+msgid "Project"
+msgstr "專案"
+
+#: dashboards/admin/networks/forms.py:37 dashboards/admin/networks/forms.py:74
+#: dashboards/admin/networks/tables.py:72
+#: dashboards/project/networks/tables.py:98
+#: dashboards/project/networks/templates/networks/_detail_overview.html:17
+msgid "Shared"
+msgstr ""
+
+#: dashboards/admin/networks/forms.py:46 dashboards/admin/users/forms.py:42
+msgid "Select a project"
+msgstr "選擇專案"
+
+#: dashboards/admin/networks/forms.py:58
+#, python-format
+msgid "Network %s was successfully created."
+msgstr "網路 %s 已成功建立。"
+
+#: dashboards/admin/networks/forms.py:64
+#, python-format
+msgid "Failed to create network %s"
+msgstr "無法建立網路 %s"
+
+#: dashboards/admin/networks/forms.py:71
+#: dashboards/admin/networks/templates/networks/ports/_update.html:12
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:12
+#: dashboards/admin/users/forms.py:114
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:11
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:12
+#: dashboards/project/instances/templates/instances/_detail_overview.html:11
+#: dashboards/project/networks/forms.py:39
+#: dashboards/project/networks/templates/networks/_detail_overview.html:9
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/subnets/_update.html:12
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:11
+msgid "ID"
+msgstr "ID"
+
+#: dashboards/admin/networks/forms.py:82
+#: dashboards/project/networks/forms.py:48
+#, python-format
+msgid "Network %s was successfully updated."
+msgstr "網路 %s 已成功的更新。"
+
+#: dashboards/admin/networks/forms.py:87
+#: dashboards/project/networks/forms.py:53
+#, python-format
+msgid "Failed to update network %s"
+msgstr "無法更新網路 %s"
+
+#: dashboards/admin/networks/panel.py:25
+#: dashboards/admin/networks/tables.py:35
+#: dashboards/admin/networks/tables.py:80
+#: dashboards/admin/networks/templates/networks/index.html:3
+#: dashboards/admin/networks/templates/networks/index.html:6
+#: dashboards/project/instances/workflows.py:412
+#: dashboards/project/networks/panel.py:25
+#: dashboards/project/networks/tables.py:44
+#: dashboards/project/networks/tables.py:106
+#: dashboards/project/networks/templates/networks/index.html:3
+#: dashboards/project/networks/templates/networks/index.html:6
+msgid "Networks"
+msgstr "網路"
+
+#: dashboards/admin/networks/tables.py:34
+#: dashboards/project/networks/tables.py:43
+#: dashboards/project/networks/templates/networks/subnets/index.html:3
+#: dashboards/project/networks/templates/networks/subnets/index.html:6
+msgid "Network"
+msgstr "網路"
+
+#: dashboards/admin/networks/tables.py:41
+#: dashboards/project/networks/tables.py:59
+#, python-format
+msgid "Failed to delete network %s"
+msgstr "無法刪除網路 %s"
+
+#: dashboards/admin/networks/tables.py:49
+#: dashboards/admin/networks/templates/networks/_create.html:8
+#: dashboards/admin/networks/templates/networks/_create.html:23
+#: dashboards/admin/networks/templates/networks/create.html:3
+#: dashboards/admin/networks/templates/networks/create.html:6
+#: dashboards/project/networks/tables.py:67
+#: dashboards/project/networks/workflows.py:111
+#: dashboards/project/networks/templates/networks/_create.html:7
+#: dashboards/project/networks/templates/networks/_create.html:22
+#: dashboards/project/networks/templates/networks/create.html:3
+#: dashboards/project/networks/templates/networks/create.html:6
+msgid "Create Network"
+msgstr "建立網路"
+
+#: dashboards/admin/networks/tables.py:56
+#: dashboards/admin/networks/templates/networks/_update.html:7
+#: dashboards/project/networks/tables.py:74
+#: dashboards/project/networks/templates/networks/_update.html:7
+msgid "Edit Network"
+msgstr "編輯網路"
+
+#: dashboards/admin/networks/tables.py:68
+#: dashboards/admin/networks/ports/forms.py:33
+#: dashboards/project/networks/subnets/forms.py:35
+msgid "Network Name"
+msgstr "網路名稱"
+
+#: dashboards/admin/networks/tables.py:71
+#: dashboards/project/networks/tables.py:97
+msgid "Subnets Associated"
+msgstr "關聯的子網路"
+
+#: dashboards/admin/networks/tables.py:76
+#: dashboards/admin/networks/ports/tables.py:79
+#: dashboards/project/networks/tables.py:102
+#: dashboards/project/networks/ports/tables.py:46
+#: dashboards/project/networks/templates/networks/_detail_overview.html:15
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:32
+msgid "Admin State"
+msgstr "Admin 狀態"
+
+#: dashboards/admin/networks/views.py:60
+#: dashboards/project/networks/views.py:52
+msgid "Network list can not be retrieved."
+msgstr "不能取回網路清單。"
+
+#: dashboards/admin/networks/views.py:91
+#: dashboards/project/networks/views.py:109
+msgid "Subnet list can not be retrieved."
+msgstr "不能取回子網路清單。"
+
+#: dashboards/admin/networks/views.py:103
+#: dashboards/project/networks/views.py:121
+msgid "Port list can not be retrieved."
+msgstr "不能取回連接埠清單。"
+
+#: dashboards/admin/networks/views.py:118
+#: dashboards/project/networks/views.py:134
+#: dashboards/project/networks/subnets/tables.py:96
+#, python-format
+msgid "Unable to retrieve details for network \"%s\"."
+msgstr "無法取回網路 \"%s\" 的詳細資料。"
+
+#: dashboards/admin/networks/ports/forms.py:36
+#: dashboards/project/networks/subnets/forms.py:39
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:13
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:13
+msgid "Network ID"
+msgstr "網路 ID"
+
+#: dashboards/admin/networks/ports/forms.py:42
+#: dashboards/admin/networks/ports/forms.py:74
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:34
+msgid "Device ID"
+msgstr "裝置 ID"
+
+#: dashboards/admin/networks/ports/forms.py:54
+#, python-format
+msgid "Port %s was successfully created."
+msgstr "連接埠 %s 已成功建立。"
+
+#: dashboards/admin/networks/ports/forms.py:59
+#, python-format
+msgid "Failed to create a port for network %s"
+msgstr "無法建立網路 %s 的連接埠"
+
+#: dashboards/admin/networks/ports/forms.py:84
+#, python-format
+msgid "Port %s was successfully updated."
+msgstr "連接埠 %s 已成功更新。"
+
+#: dashboards/admin/networks/ports/forms.py:89
+#, python-format
+msgid "Failed to update port %s"
+msgstr "無法更新連接埠 %s"
+
+#: dashboards/admin/networks/ports/tables.py:34
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:6
+msgid "Port"
+msgstr "連接埠"
+
+#: dashboards/admin/networks/ports/tables.py:35
+#: dashboards/admin/networks/ports/tables.py:83
+#: dashboards/project/networks/ports/tables.py:53
+msgid "Ports"
+msgstr "連接埠"
+
+#: dashboards/admin/networks/ports/tables.py:41
+#: dashboards/admin/networks/subnets/tables.py:39
+#: dashboards/project/networks/subnets/tables.py:51
+#, python-format
+msgid "Failed to delete subnet %s"
+msgstr "無法刪除子網路 %s"
+
+#: dashboards/admin/networks/ports/tables.py:51
+#: dashboards/admin/networks/templates/networks/ports/_create.html:8
+#: dashboards/admin/networks/templates/networks/ports/_create.html:23
+#: dashboards/admin/networks/templates/networks/ports/create.html:3
+#: dashboards/admin/networks/templates/networks/ports/create.html:6
+msgid "Create Port"
+msgstr "建立連接埠"
+
+#: dashboards/admin/networks/ports/tables.py:62
+#: dashboards/admin/networks/templates/networks/ports/_update.html:7
+msgid "Edit Port"
+msgstr "編輯連接埠"
+
+#: dashboards/admin/networks/ports/tables.py:75
+#: dashboards/project/networks/ports/tables.py:42
+msgid "Fixed IPs"
+msgstr "固定 IP"
+
+#: dashboards/admin/networks/ports/tables.py:76
+#: dashboards/project/networks/ports/tables.py:43
+msgid "Device Attached"
+msgstr "裝置已附加"
+
+#: dashboards/admin/networks/ports/tabs.py:32
+#: dashboards/admin/overview/panel.py:29
+#: dashboards/admin/overview/templates/overview/usage.html:6
+#: dashboards/project/images_and_snapshots/images/tabs.py:27
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:27
+#: dashboards/project/instances/tabs.py:26
+#: dashboards/project/networks/ports/tabs.py:32
+#: dashboards/project/networks/subnets/tabs.py:32
+#: dashboards/project/overview/panel.py:29
+#: dashboards/project/overview/templates/overview/usage.html:6
+#: dashboards/project/volumes/tabs.py:27
+msgid "Overview"
+msgstr "總覽"
+
+#: dashboards/admin/networks/ports/tabs.py:42
+#: dashboards/project/networks/ports/tabs.py:42
+msgid "Unable to retrieve port details."
+msgstr "無法取回連接埠詳細資料。"
+
+#: dashboards/admin/networks/ports/views.py:49
+#: dashboards/admin/networks/subnets/views.py:49
+#: dashboards/project/networks/subnets/views.py:54
+msgid "Unable to retrieve network."
+msgstr "無法取回網路。"
+
+#: dashboards/admin/networks/ports/views.py:82
+msgid "Unable to retrieve port details"
+msgstr "無法取回連接埠詳細資料"
+
+#: dashboards/admin/networks/subnets/forms.py:43
+#, python-format
+msgid "Failed to retrieve network %s for a subnet"
+msgstr "無法取回網路 %s 子網路"
+
+#: dashboards/admin/networks/subnets/tables.py:32
+#: dashboards/project/networks/subnets/tables.py:44
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:6
+msgid "Subnet"
+msgstr "子網路"
+
+#: dashboards/admin/networks/subnets/tables.py:33
+#: dashboards/admin/networks/subnets/tables.py:81
+#: dashboards/project/networks/subnets/tables.py:45
+#: dashboards/project/networks/subnets/tables.py:104
+msgid "Subnets"
+msgstr "子網路"
+
+#: dashboards/admin/networks/subnets/tables.py:49
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:8
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:23
+#: dashboards/admin/networks/templates/networks/subnets/create.html:3
+#: dashboards/admin/networks/templates/networks/subnets/create.html:6
+#: dashboards/project/networks/workflows.py:53
+#: dashboards/project/networks/subnets/tables.py:61
+#: dashboards/project/networks/templates/networks/subnets/_create.html:8
+#: dashboards/project/networks/templates/networks/subnets/_create.html:23
+#: dashboards/project/networks/templates/networks/subnets/create.html:3
+#: dashboards/project/networks/templates/networks/subnets/create.html:6
+msgid "Create Subnet"
+msgstr "建立子網路"
+
+#: dashboards/admin/networks/subnets/tables.py:60
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:7
+#: dashboards/project/networks/subnets/tables.py:72
+#: dashboards/project/networks/templates/networks/subnets/_update.html:7
+msgid "Edit Subnet"
+msgstr "編輯子網路"
+
+#: dashboards/admin/networks/subnets/tables.py:72
+#: dashboards/project/access_and_security/security_groups/forms.py:91
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:15
+msgid "CIDR"
+msgstr "CIDR"
+
+#: dashboards/admin/networks/subnets/tables.py:73
+#: dashboards/project/networks/workflows.py:66
+#: dashboards/project/networks/subnets/forms.py:53
+#: dashboards/project/networks/subnets/tables.py:85
+msgid "IP Version"
+msgstr "IP 版本"
+
+#: dashboards/admin/networks/subnets/tables.py:74
+#: dashboards/project/networks/subnets/forms.py:54
+#: dashboards/project/networks/subnets/forms.py:104
+#: dashboards/project/networks/subnets/tables.py:86
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:19
+msgid "Gateway IP"
+msgstr "閘道器 IP"
+
+#: dashboards/admin/networks/subnets/views.py:82
+#: dashboards/project/networks/subnets/views.py:86
+msgid "Unable to retrieve subnet details"
+msgstr "無法取回子網路詳細資料"
+
+#: dashboards/admin/networks/templates/networks/_create.html:18
+#: dashboards/project/networks/templates/networks/_create.html:17
+msgid "Select a name for your network."
+msgstr "選擇您的網路名稱。"
+
+#: dashboards/admin/networks/templates/networks/_update.html:16
+#: dashboards/admin/networks/templates/networks/ports/_update.html:21
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:25
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:17
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_update.html:16
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:17
+#: dashboards/project/instances/templates/instances/_update.html:16
+#: dashboards/project/networks/templates/networks/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_update.html:25
+#: dashboards/settings/ec2/templates/ec2/download_form.html:17
+#: dashboards/settings/project/templates/project/_openrc.html:24
+#: dashboards/settings/user/templates/user/_settings.html:17
+msgid "Description:"
+msgstr "詳述:"
+
+#: dashboards/admin/networks/templates/networks/_update.html:17
+#: dashboards/project/networks/templates/networks/_update.html:17
+msgid "You may update the editable properties of your network here."
+msgstr "您可以在這裡更新網路的可編輯屬性。"
+
+#: dashboards/admin/networks/templates/networks/_update.html:22
+#: dashboards/admin/networks/templates/networks/ports/_update.html:27
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:31
+#: dashboards/project/instances/templates/instances/_update.html:22
+#: dashboards/project/networks/templates/networks/_update.html:22
+#: dashboards/project/networks/templates/networks/subnets/_update.html:31
+msgid "Save Changes"
+msgstr "儲存變更"
+
+#: dashboards/admin/networks/templates/networks/update.html:3
+#: dashboards/admin/networks/templates/networks/update.html:6
+#: dashboards/project/networks/templates/networks/update.html:3
+#: dashboards/project/networks/templates/networks/update.html:6
+msgid "Update Network"
+msgstr "更新網路"
+
+#: dashboards/admin/networks/templates/networks/ports/_create.html:18
+msgid ""
+"You can create a port for the network. If you specify device ID to be "
+"attached, the device specified will be attached to the port created."
+msgstr ""
+"您可以建立網路的連接埠。如果您指定要附加的裝置 ID,指定的 ID 就會附加到建立好"
+"的連接埠。"
+
+#: dashboards/admin/networks/templates/networks/ports/_update.html:22
+msgid "You may update the editable properties of your port here."
+msgstr "您可以在這裡更新連接埠的可編輯屬性。"
+
+#: dashboards/admin/networks/templates/networks/ports/update.html:3
+#: dashboards/admin/networks/templates/networks/ports/update.html:6
+msgid "Update Port"
+msgstr "更新連接埠"
+
+#: dashboards/admin/networks/templates/networks/subnets/_create.html:18
+#: dashboards/project/networks/templates/networks/subnets/_create.html:18
+msgid ""
+"You can create a subnet for the network. Any network address can be "
+"specified unless the network address does not overlap other subnets in the "
+"network."
+msgstr ""
+"您可以建立網路的子網路。您可以指定任何網路位址,只要它沒有與網路中的子網路重"
+"疊到。"
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:14
+#: dashboards/project/networks/workflows.py:58
+#: dashboards/project/networks/subnets/forms.py:45
+#: dashboards/project/networks/subnets/tables.py:84
+#: dashboards/project/networks/templates/networks/subnets/_update.html:14
+msgid "Network Address"
+msgstr "網路位址"
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:16
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:17
+#: dashboards/project/networks/templates/networks/subnets/_update.html:16
+msgid "IP version"
+msgstr "IP 版本"
+
+#: dashboards/admin/networks/templates/networks/subnets/_update.html:26
+#: dashboards/project/networks/templates/networks/subnets/_update.html:26
+msgid "You may update the editable properties of your subnet here."
+msgstr "您可以在這裡更新子網路的可編輯屬性。"
+
+#: dashboards/admin/networks/templates/networks/subnets/index.html:3
+#: dashboards/admin/networks/templates/networks/subnets/index.html:6
+#: dashboards/project/networks/templates/networks/detail.html:3
+msgid "Network Detail"
+msgstr "網路詳細資料"
+
+#: dashboards/admin/networks/templates/networks/subnets/update.html:3
+#: dashboards/admin/networks/templates/networks/subnets/update.html:6
+#: dashboards/project/networks/templates/networks/subnets/update.html:3
+#: dashboards/project/networks/templates/networks/subnets/update.html:6
+msgid "Update Subnet"
+msgstr "更新子網路"
+
+#: dashboards/admin/overview/templates/overview/usage.html:3
+msgid "Usage Overview"
+msgstr "使用量總覽"
+
+#: dashboards/admin/overview/templates/overview/usage.html:12
+msgid "Monitoring"
+msgstr "監測"
+
+#: dashboards/admin/projects/panel.py:29
+#: dashboards/admin/projects/tables.py:66
+#: dashboards/admin/projects/tables.py:95
+#: dashboards/admin/projects/templates/projects/index.html:8
+#: templates/403.html:24 templates/404.html:23 templates/500.html:23
+msgid "Projects"
+msgstr "專案"
+
+#: dashboards/admin/projects/tables.py:19
+msgid "Modify Users"
+msgstr "修改使用者"
+
+#: dashboards/admin/projects/tables.py:32
+msgid "View Usage"
+msgstr "檢視使用量"
+
+#: dashboards/admin/projects/tables.py:39
+#: dashboards/admin/projects/templates/projects/_create.html:8
+#: dashboards/admin/projects/templates/projects/_create.html:23
+#: dashboards/admin/projects/templates/projects/create.html:6
+msgid "Create Project"
+msgstr "建立專案"
+
+#: dashboards/admin/projects/tables.py:46
+#: dashboards/admin/projects/workflows.py:269
+#: dashboards/admin/projects/templates/projects/update.html:3
+#: dashboards/admin/projects/templates/projects/update.html:6
+msgid "Edit Project"
+msgstr "編輯專案"
+
+#: dashboards/admin/projects/tables.py:90
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:60
+#: dashboards/project/networks/templates/networks/_detail_overview.html:11
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:15
+msgid "Project ID"
+msgstr "專案ID"
+
+#: dashboards/admin/projects/tables.py:91
+#: dashboards/admin/projects/workflows.py:76
+#: dashboards/admin/projects/workflows.py:251
+#: dashboards/admin/services/tables.py:42 dashboards/admin/users/tables.py:40
+#: dashboards/admin/users/tables.py:115
+msgid "Enabled"
+msgstr "已啟用"
+
+#: dashboards/admin/projects/tables.py:104
+msgid "Remove"
+msgstr "移除"
+
+#: dashboards/admin/projects/tables.py:105
+msgid "Removed"
+msgstr "已移除"
+
+#: dashboards/admin/projects/tables.py:106 dashboards/admin/users/tables.py:41
+#: dashboards/admin/users/tables.py:75
+#: dashboards/project/instances/workflows.py:39
+msgid "User"
+msgstr "使用者"
+
+#: dashboards/admin/projects/tables.py:107 dashboards/admin/users/panel.py:29
+#: dashboards/admin/users/tables.py:42 dashboards/admin/users/tables.py:76
+#: dashboards/admin/users/tables.py:122
+#: dashboards/admin/users/templates/users/index.html:8
+msgid "Users"
+msgstr "使用者"
+
+#: dashboards/admin/projects/tables.py:125
+msgid "Unable to retrieve role information."
+msgstr "無法取回角色資訊。"
+
+#: dashboards/admin/projects/tables.py:130
+msgid "Roles"
+msgstr "角色"
+
+#: dashboards/admin/projects/tables.py:134
+msgid "Users For Project"
+msgstr "專案使用者"
+
+#: dashboards/admin/projects/tables.py:142
+msgid "Add To Project"
+msgstr "加入專案"
+
+#: dashboards/admin/projects/tables.py:154
+msgid "Add New Users"
+msgstr "新增使用者"
+
+#: dashboards/admin/projects/views.py:67
+msgid "Unable to retrieve project information."
+msgstr "無法取回專案資訊。"
+
+#: dashboards/admin/projects/views.py:87
+msgid "Unable to retrieve project list."
+msgstr "無法取回專案清單。"
+
+#: dashboards/admin/projects/views.py:110
+msgid "Unable to retrieve users."
+msgstr "無法取得使用者"
+
+#: dashboards/admin/projects/views.py:154
+msgid "Unable to retrieve default quota values."
+msgstr "無法取回預設的限額數值。"
+
+#: dashboards/admin/projects/views.py:182
+msgid "Unable to retrieve project details."
+msgstr "無法取回專案詳細資料。"
+
+#: dashboards/admin/projects/workflows.py:37
+msgid "Injected File Content Bytes"
+msgstr "注入檔案內容位元數"
+
+#: dashboards/admin/projects/workflows.py:38
+msgid "Metadata Items"
+msgstr "中介資料(Metadata)的物件數"
+
+#: dashboards/admin/projects/workflows.py:41
+msgid "Injected Files"
+msgstr "注入檔案數"
+
+#: dashboards/admin/projects/workflows.py:44
+#: dashboards/admin/volumes/panel.py:9 dashboards/admin/volumes/tables.py:15
+#: dashboards/admin/volumes/templates/volumes/index.html:3
+#: dashboards/admin/volumes/templates/volumes/index.html:6
+#: dashboards/project/volumes/panel.py:25
+#: dashboards/project/volumes/tables.py:38
+#: dashboards/project/volumes/tables.py:171
+#: dashboards/project/volumes/tables.py:183
+#: dashboards/project/volumes/templates/volumes/index.html:3
+#: dashboards/project/volumes/templates/volumes/index.html:6
+msgid "Volumes"
+msgstr "容量"
+
+#: dashboards/admin/projects/workflows.py:45
+msgid "Gigabytes"
+msgstr "儲存空間 (Gigabytes)"
+
+#: dashboards/admin/projects/workflows.py:46
+msgid "RAM (MB)"
+msgstr "RAM (MB)"
+
+#: dashboards/admin/projects/workflows.py:47
+#: dashboards/project/access_and_security/floating_ips/tables.py:50
+#: dashboards/project/access_and_security/floating_ips/tables.py:128
+msgid "Floating IPs"
+msgstr "浮動IP"
+
+#: dashboards/admin/projects/workflows.py:50
+msgid "Quota"
+msgstr "限額"
+
+#: dashboards/admin/projects/workflows.py:52
+msgid "From here you can set quotas (max limits) for the project."
+msgstr "從這裡可以設定專案的限額 (最大限制)。"
+
+#: dashboards/admin/projects/workflows.py:81
+#: dashboards/admin/projects/workflows.py:254
+msgid "Project Info"
+msgstr "專案資訊"
+
+#: dashboards/admin/projects/workflows.py:82
+#: dashboards/admin/projects/templates/projects/_create.html:18
+msgid "From here you can create a new project to organize users."
+msgstr "您可以在這裡建立新專案以管理使用者"
+
+#: dashboards/admin/projects/workflows.py:101
+msgid "Unable to retrieve user list. Please try again later."
+msgstr "無法取回使用者清單。請稍後再試一次。"
+
+#: dashboards/admin/projects/workflows.py:155
+#: dashboards/admin/projects/templates/projects/_update_members.html:16
+msgid "Project Members"
+msgstr "專案成員"
+
+#: dashboards/admin/projects/workflows.py:169
+#: dashboards/admin/users/views.py:47
+msgid "Unable to retrieve user list."
+msgstr "無法取回使用者清單。"
+
+#: dashboards/admin/projects/workflows.py:180
+msgid "Add Project"
+msgstr "加入專案"
+
+#: dashboards/admin/projects/workflows.py:181
+msgid "Finish"
+msgstr "結束"
+
+#: dashboards/admin/projects/workflows.py:182
+#, python-format
+msgid "Created new project \"%s\"."
+msgstr "已建立新專案 \"%s\"。"
+
+#: dashboards/admin/projects/workflows.py:183
+#, python-format
+msgid "Unable to create project \"%s\"."
+msgstr "無法建立專案 \"%s\"。"
+
+#: dashboards/admin/projects/workflows.py:227
+#, python-format
+msgid "Failed to add %s project members and set project quotas."
+msgstr "無法加入 %s 專案成員並設定專案限額。"
+
+#: dashboards/admin/projects/workflows.py:246
+msgid "Unable to set project quotas."
+msgstr "無法設定專案限額。"
+
+#: dashboards/admin/projects/workflows.py:256
+msgid "From here you can edit the project details."
+msgstr "從這裡您可以編輯專案詳細資料。"
+
+#: dashboards/admin/projects/workflows.py:271
+#, python-format
+msgid "Modified project \"%s\"."
+msgstr "修改的專案 \"%s\"。"
+
+#: dashboards/admin/projects/workflows.py:272
+#, python-format
+msgid "Unable to modify project \"%s\"."
+msgstr "無法修改的專案 \"%s\"。"
+
+#: dashboards/admin/projects/workflows.py:342
+#, python-format
+msgid "Failed to modify %s project members and update project quotas."
+msgstr "無法修改 %s 專案成員與更新專案限額。"
+
+#: dashboards/admin/projects/workflows.py:363
+msgid ""
+"Modified project information and members, but unable to modify project "
+"quotas."
+msgstr "修改專案資訊與成員,但無法修改專案限額。"
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:8
+#: dashboards/admin/projects/templates/projects/add_user.html:3
+#: dashboards/admin/projects/templates/projects/add_user.html:6
+msgid "Add User To Project"
+msgstr "新增使用者到專案"
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:18
+msgid "Select the user role for the project."
+msgstr "選擇使用者的專案角色"
+
+#: dashboards/admin/projects/templates/projects/_add_user.html:23
+msgid "Add"
+msgstr "新增"
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:7
+#, python-format
+msgid "Create User for project '%(tenant_name)s'."
+msgstr "建立專案 '%(tenant_name)s' 的使用者。"
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:18
+msgid "From here you can create a new user to add to this project."
+msgstr "從這裡您可以建立新的使用者並加入這個專案。"
+
+#: dashboards/admin/projects/templates/projects/_create_user.html:23
+#: dashboards/admin/users/tables.py:20
+#: dashboards/admin/users/templates/users/_create.html:7
+#: dashboards/admin/users/templates/users/_create.html:22
+#: dashboards/admin/users/templates/users/create.html:7
+msgid "Create User"
+msgstr "建立使用者"
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:7
+#: dashboards/admin/projects/templates/projects/_quotas.html:22
+msgid "Update Quota"
+msgstr "更新配額"
+
+#: dashboards/admin/projects/templates/projects/_quotas.html:17
+#, python-format
+msgid ""
+"From here you can edit quotas (max limits) for the project %(tenant.name)s."
+msgstr "您可以在這裡編輯專案%(tenant.name)s的資源配額(最大用額)。"
+
+#: dashboards/admin/projects/templates/projects/_update.html:8
+#: dashboards/admin/projects/templates/projects/_update.html:23
+#: dashboards/admin/projects/templates/projects/quotas.html:6
+msgid "Update Project"
+msgstr "更新專案"
+
+#: dashboards/admin/projects/templates/projects/_update.html:18
+msgid "From here you can edit a project."
+msgstr "您可以在這編輯專案"
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:7
+msgid ""
+"From here you can add and remove members to this project from the list of "
+"all available users."
+msgstr "這裡您可以從所有可用使用者清單中將成員加入這個專案或移除。"
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:10
+msgid "All Users"
+msgstr "所有使用者"
+
+#: dashboards/admin/projects/templates/projects/_update_members.html:25
+#: dashboards/admin/projects/templates/projects/_update_members.html:32
+msgid "No users found."
+msgstr "找不到使用者。"
+
+#: dashboards/admin/projects/templates/projects/create_user.html:3
+#: dashboards/admin/projects/templates/projects/create_user.html:6
+msgid "Add New User"
+msgstr "加入新的使用者"
+
+#: dashboards/admin/projects/templates/projects/usage.html:3
+msgid "Project Usage Overview"
+msgstr "專案使用量總覽"
+
+#: dashboards/admin/projects/templates/projects/usage.html:7
+msgid "Project Usage"
+msgstr "專案使用量"
+
+#: dashboards/admin/projects/templates/projects/users.html:7
+msgid "Users for Project"
+msgstr "專案使用者"
+
+#: dashboards/admin/quotas/panel.py:29 dashboards/admin/quotas/tables.py:36
+msgid "Quotas"
+msgstr "配額"
+
+#: dashboards/admin/quotas/tables.py:28
+msgid "Quota Name"
+msgstr "配額名稱"
+
+#: dashboards/admin/quotas/tables.py:29
+msgid "Limit"
+msgstr "限制"
+
+#: dashboards/admin/quotas/views.py:46
+msgid "Unable to get quota info."
+msgstr "無法取得限額資訊。"
+
+#: dashboards/admin/quotas/templates/quotas/index.html:8
+msgid "Default Quotas"
+msgstr "預設配額"
+
+#: dashboards/admin/services/panel.py:29
+#: dashboards/admin/services/tables.py:47
+#: dashboards/admin/services/templates/services/index.html:8
+msgid "Services"
+msgstr "服務"
+
+#: dashboards/admin/services/tables.py:37
+msgid "Id"
+msgstr "Id"
+
+#: dashboards/admin/services/tables.py:39
+msgid "Service"
+msgstr "服務"
+
+#: dashboards/admin/users/forms.py:54
+msgid "Passwords do not match."
+msgstr "密碼不符"
+
+#: dashboards/admin/users/forms.py:62 dashboards/admin/users/forms.py:115
+#: dashboards/admin/users/tables.py:108
+msgid "User Name"
+msgstr "使用者名稱"
+
+#: dashboards/admin/users/forms.py:63 dashboards/admin/users/forms.py:116
+#: dashboards/admin/users/tables.py:109
+msgid "Email"
+msgstr "電子郵件"
+
+#: dashboards/admin/users/forms.py:65 dashboards/admin/users/forms.py:117
+msgid "Password"
+msgstr "密碼"
+
+#: dashboards/admin/users/forms.py:70 dashboards/admin/users/forms.py:124
+msgid "Confirm Password"
+msgstr "密碼確認"
+
+#: dashboards/admin/users/forms.py:73 dashboards/admin/users/forms.py:127
+msgid "Primary Project"
+msgstr "主要專案"
+
+#: dashboards/admin/users/forms.py:75
+msgid "Role"
+msgstr "角色"
+
+#: dashboards/admin/users/forms.py:96
+#, python-format
+msgid "User \"%s\" was successfully created."
+msgstr "使用者\"%s\"已被成功建立。"
+
+#: dashboards/admin/users/forms.py:106
+msgid "Unable to add userto primary project."
+msgstr "無法加入使用者到主要專案。"
+
+#: dashboards/admin/users/forms.py:110
+msgid "Unable to create user."
+msgstr "無法建立使用者。"
+
+#: dashboards/admin/users/forms.py:151
+msgid "name"
+msgstr "名稱"
+
+#: dashboards/admin/users/forms.py:151
+msgid "email"
+msgstr "電子郵件"
+
+#: dashboards/admin/users/forms.py:160
+msgid "primary project"
+msgstr "主要專案"
+
+#: dashboards/admin/users/forms.py:173
+#, python-format
+msgid "The user %s has no role defined for"
+msgstr "使用者 %s 沒有定義角色"
+
+#: dashboards/admin/users/forms.py:181
+msgid "password"
+msgstr "密碼"
+
+#: dashboards/admin/users/forms.py:190
+msgid "User has been updated successfully."
+msgstr "使用者已經成功的更新。"
+
+#: dashboards/admin/users/forms.py:194
+#, python-format
+msgid "Unable to update %(attributes)s for the user."
+msgstr "無法更新使用者的 %(attributes)s。"
+
+#: dashboards/admin/users/tables.py:32
+#: dashboards/project/images_and_snapshots/images/tables.py:68
+msgid "Edit"
+msgstr "編輯"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Enable"
+msgstr "啟用"
+
+#: dashboards/admin/users/tables.py:39
+msgid "Disable"
+msgstr "停用"
+
+#: dashboards/admin/users/tables.py:40
+msgid "Disabled"
+msgstr "已停用"
+
+#: dashboards/admin/users/tables.py:63
+msgid "You cannot disable the user you are currently logged in as."
+msgstr "您不能停用您目前登入使用的使用者"
+
+#: dashboards/admin/users/tables.py:114
+msgid "User ID"
+msgstr "使用者 ID"
+
+#: dashboards/admin/users/views.py:70
+msgid "Unable to update user."
+msgstr "無法更新使用者。"
+
+#: dashboards/admin/users/views.py:104
+msgid "Unable to retrieve user roles."
+msgstr "無法取回使用者角色。"
+
+#: dashboards/admin/users/templates/users/_create.html:17
+msgid "From here you can create a new user and assign them to a project."
+msgstr "您可以在這裡建立使用者及將其分配到專案。"
+
+#: dashboards/admin/users/templates/users/_update.html:7
+#: dashboards/admin/users/templates/users/_update.html:22
+#: dashboards/admin/users/templates/users/update.html:7
+msgid "Update User"
+msgstr "更新使用者"
+
+#: dashboards/admin/users/templates/users/_update.html:17
+msgid ""
+"From here you can edit the user's details, including their default project."
+msgstr "從這裡您可以編輯使用者的詳細資料,包含他們的預設專案。"
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:3
+#: dashboards/project/volumes/templates/volumes/detail.html:3
+msgid "Volume Details"
+msgstr "容量詳述"
+
+#: dashboards/admin/volumes/templates/volumes/detail.html:6
+#: dashboards/project/volumes/templates/volumes/detail.html:6
+msgid "Volume Detail"
+msgstr "容量詳述"
+
+#: dashboards/project/dashboard.py:24
+msgid "Manage Compute"
+msgstr "運算管理"
+
+#: dashboards/project/dashboard.py:35
+msgid "Object Store"
+msgstr "物件儲存"
+
+#: dashboards/project/access_and_security/panel.py:26
+#: dashboards/project/instances/workflows.py:348
+msgid "Access & Security"
+msgstr "存取 & 安全性"
+
+#: dashboards/project/access_and_security/views.py:51
+msgid "Unable to retrieve keypair list."
+msgstr "無法取得金鑰列表。"
+
+#: dashboards/project/access_and_security/views.py:60
+#: dashboards/project/access_and_security/security_groups/views.py:74
+msgid "Unable to retrieve security groups."
+msgstr "無法取得安全性群組"
+
+#: dashboards/project/access_and_security/views.py:69
+#: dashboards/project/access_and_security/floating_ips/workflows.py:49
+msgid "Unable to retrieve floating IP addresses."
+msgstr "無法取回浮動 IP 位址。"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:32
+msgid "Pool"
+msgstr "储备池"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:43
+#, python-format
+msgid "Allocated Floating IP %(ip)s."
+msgstr "分配的浮動 IP %(ip)s。"
+
+#: dashboards/project/access_and_security/floating_ips/forms.py:47
+msgid "Unable to allocate Floating IP."
+msgstr "無法分配浮動IP"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:37
+msgid "Allocate IP To Project"
+msgstr "分配IP到專案"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:47
+msgid "Release"
+msgstr "釋放"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:48
+msgid "Released"
+msgstr "已釋放"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:49
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:22
+msgid "Floating IP"
+msgstr "浮動IP"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:59
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/associate.html:6
+#: dashboards/project/instances/tables.py:219
+msgid "Associate Floating IP"
+msgstr "配給浮動IP"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:76
+msgid "Disassociate Floating IP"
+msgstr "解除浮動 IP 關聯"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:90
+#, python-format
+msgid "Successfully disassociated Floating IP: %s"
+msgstr "已成功釋放浮動IP: %s"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:94
+msgid "Unable to disassociate floating IP."
+msgstr "無法釋放浮動IP。"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:114
+#: dashboards/project/access_and_security/floating_ips/workflows.py:36
+#: dashboards/project/instances/tables.py:69
+#: dashboards/project/instances/tables.py:89
+#: dashboards/project/instances/tables.py:106
+#: dashboards/project/instances/tables.py:135
+#: dashboards/project/volumes/tables.py:206
+msgid "Instance"
+msgstr "執行個體"
+
+#: dashboards/project/access_and_security/floating_ips/tables.py:117
+msgid "Floating IP Pool"
+msgstr "浮動IP集"
+
+#: dashboards/project/access_and_security/floating_ips/views.py:65
+msgid "Unable to retrieve floating IP pools."
+msgstr ""
+
+#: dashboards/project/access_and_security/floating_ips/views.py:68
+msgid "No floating IP pools available."
+msgstr "沒有任何存在的浮動IP集"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:40
+msgid "Select the IP address you wish to associate with the selected instance."
+msgstr "選擇您希望選取的個體關聯的 IP 位址。"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:53
+msgid "Select an IP address"
+msgstr "選擇 IP 位址"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:55
+msgid "No IP addresses available"
+msgstr "沒有 IP 位址可用"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:76
+#: dashboards/project/volumes/forms.py:160
+msgid "Select an instance"
+msgstr "選擇一個執行個體"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:78
+#: dashboards/project/volumes/forms.py:162
+msgid "No instances available"
+msgstr "沒有可用的執行個體"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:97
+msgid "Manage Floating IP Associations"
+msgstr "管理浮動 IP 關聯"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:98
+msgid "Associate"
+msgstr "關聯"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:99
+#, python-format
+msgid "IP address %s associated."
+msgstr "IP 位址 %s 已關聯。"
+
+#: dashboards/project/access_and_security/floating_ips/workflows.py:100
+#, python-format
+msgid "Unable to associate IP address %s."
+msgstr "無法關聯 IP 位址 %s。"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:38
+#: dashboards/project/access_and_security/keypairs/forms.py:49
+#: dashboards/project/access_and_security/keypairs/tables.py:52
+msgid "Keypair Name"
+msgstr "金鑰名稱"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:40
+msgid ""
+"Keypair names may only contain letters, numbers, underscores and hyphens."
+msgstr "金鑰名稱只接受英文字母,數字,下劃線(_)和連字符號(-)"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:51
+msgid "Public Key"
+msgstr "公鑰內容"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:60
+#, python-format
+msgid "Successfully imported public key: %s"
+msgstr "已成功匯入公鑰: %s"
+
+#: dashboards/project/access_and_security/keypairs/forms.py:65
+msgid "Unable to import keypair."
+msgstr "無法匯入金鑰。"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:30
+#: dashboards/project/instances/tables.py:295
+#: dashboards/project/instances/workflows.py:335
+msgid "Keypair"
+msgstr "金鑰"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:31
+#: dashboards/project/access_and_security/keypairs/tables.py:60
+msgid "Keypairs"
+msgstr "金鑰"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:39
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/import.html:6
+msgid "Import Keypair"
+msgstr "匯入金鑰"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:46
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/create.html:6
+msgid "Create Keypair"
+msgstr "建立金鑰"
+
+#: dashboards/project/access_and_security/keypairs/tables.py:53
+msgid "Fingerprint"
+msgstr "金鑰指紋"
+
+#: dashboards/project/access_and_security/keypairs/views.py:74
+#, python-format
+msgid "Unable to create keypair: %(exc)s"
+msgstr "無法建立金鑰: %(exc)s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:46
+#, python-format
+msgid "Successfully created security group: %s"
+msgstr "成功的建立安全性群組:%s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:52
+msgid "Unable to create security group."
+msgstr "無法建立安全性群組"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:57
+#: dashboards/project/access_and_security/security_groups/tables.py:93
+msgid "IP Protocol"
+msgstr "IP協定"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:61
+msgid "The protocol which this rule should be applied to."
+msgstr "這個規則要套用的協定。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:65
+#: dashboards/project/access_and_security/security_groups/forms.py:71
+#: dashboards/project/access_and_security/security_groups/tables.py:95
+msgid "From Port"
+msgstr "從端口"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:66
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP type in the range (-1: 255)"
+msgstr ""
+"TCP/UDP: 請輸入介於1到65535的整數。 ICMP: 請輸入介於(-1: 255)的ICMP類別代"
+"號"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:72
+#: dashboards/project/images_and_snapshots/images/tables.py:115
+msgid "Type"
+msgstr "類別"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:74
+#: dashboards/project/access_and_security/security_groups/forms.py:80
+#: dashboards/project/access_and_security/security_groups/tables.py:96
+msgid "To Port"
+msgstr "到端口"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:75
+msgid ""
+"TCP/UDP: Enter integer value between 1 and 65535. ICMP: enter a value for "
+"ICMP code in the range (-1: 255)"
+msgstr ""
+"TCP/UDP: 請輸入介於1到65535的整數。 ICMP: 請輸入介於(-1: 255)的ICMP類別代"
+"號"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:81
+msgid "Code"
+msgstr "代號"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:84
+msgid "Source Group"
+msgstr "來源群組"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:86
+msgid ""
+"To specify an allowed IP range, select CIDR. To allow access from all "
+"members of another security group select Source Group."
+msgstr ""
+"要指定允許的 IP 範圍,請選擇 CIDR。要允許從另一個安全性群組的所有成員的存取,"
+"請選擇安全性群組。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:94
+msgid "Classless Inter-Domain Routing (e.g. 192.168.0.0/24)"
+msgstr "Classless Inter-Domain Routing (例如192.168.0.0/24)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:121
+msgid "The ICMP type is invalid."
+msgstr "ICMP 類型是無效的。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:124
+msgid "The ICMP code is invalid."
+msgstr "ICMP 代碼是無效的。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:127
+msgid "The ICMP type not in range (-1, 255)"
+msgstr "ICMP 類型不在範圍中 (-1, 255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:130
+msgid "The ICMP code not in range (-1, 255)"
+msgstr "ICMP 代碼不在範圍中 (-1, 255)"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:134
+msgid "The \"from\" port number is invalid."
+msgstr "\"從端口\"不符合條件"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:137
+msgid "The \"to\" port number is invalid."
+msgstr "\"到端口\"不符合條件"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:140
+msgid ""
+"The \"to\" port number must be greater than or equal to the \"from\" port "
+"number."
+msgstr "\"到端口\"必須是大於或等於\"從端口\"的整數"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:146
+msgid "Either CIDR or Source Group may be specified, but not both."
+msgstr "只能指定CIDR或安全性群組,不能同時全選。"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:168
+#, python-format
+msgid "Successfully added rule: %s"
+msgstr "已成功新增規則: %s"
+
+#: dashboards/project/access_and_security/security_groups/forms.py:173
+msgid "Unable to add rule to security group."
+msgstr "無法加入規則到安全性群組。"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:31
+msgid "Security Group"
+msgstr "安全性群組"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:32
+#: dashboards/project/access_and_security/security_groups/tables.py:66
+#: dashboards/project/instances/workflows.py:340
+#: dashboards/project/instances/templates/instances/_detail_overview.html:49
+msgid "Security Groups"
+msgstr "安全性群組"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:45
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:7
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:23
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/create.html:6
+msgid "Create Security Group"
+msgstr "建立安全性群組"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:52
+msgid "Edit Rules"
+msgstr "編輯規則"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:72
+msgid "Rule"
+msgstr "規則"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:73
+msgid "Rules"
+msgstr "規則"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:97
+msgid "Source"
+msgstr "來源"
+
+#: dashboards/project/access_and_security/security_groups/tables.py:107
+msgid "Security Group Rules"
+msgstr "安全性群組規則"
+
+#: dashboards/project/access_and_security/security_groups/views.py:60
+msgid "Unable to retrieve security group."
+msgstr "無法取得安全性群組"
+
+#: dashboards/project/access_and_security/security_groups/views.py:80
+#, python-format
+msgid "%s (current)"
+msgstr "%s (目前的)"
+
+#: dashboards/project/access_and_security/templates/access_and_security/index.html:6
+msgid "Access &amp; Security"
+msgstr "存取 &amp; 安全性"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:8
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/allocate.html:3
+msgid "Allocate Floating IP"
+msgstr "分配浮動IP"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:18
+msgid "Allocate a floating IP from a given floating ip pool."
+msgstr "從浮動IP集分配一個浮動IP"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:20
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:19
+msgid "Project Quotas"
+msgstr "專案配額"
+
+#: dashboards/project/access_and_security/templates/access_and_security/floating_ips/_allocate.html:31
+msgid "Allocate IP"
+msgstr "分配IP"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:17
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:17
+msgid ""
+"Keypairs are ssh credentials which are injected into images when they are "
+"launched. Creating a new key pair registers the public key and downloads the "
+"private key (a .pem file)."
+msgstr ""
+"金鑰是用來注入到啟動映像的ssh認證。建立一個新的金鑰會自動把公鑰註冊及下載一份"
+"私鑰(.pem檔案)"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_create.html:18
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/_import.html:18
+msgid "Protect and use the key as you would any normal ssh private key."
+msgstr "請妥善安全保管及使用這ssh私鑰"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:3
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:6
+msgid "Download Keypair"
+msgstr "下載金鑰"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:11
+#, python-format
+msgid ""
+"The keypair &quot;%(keypair_name)s&quot; should download automatically. If "
+"not use the link below."
+msgstr "金鑰&quot;%(keypair_name)s&quot;應該會自動地下載。否則請使用以下連結"
+
+#: dashboards/project/access_and_security/templates/access_and_security/keypairs/download.html:15
+#, python-format
+msgid "Download keypair &quot;%(keypair_name)s&quot;"
+msgstr "下載金鑰&quot;%(keypair_name)s&quot;"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_create.html:18
+msgid "From here you can create a new security group"
+msgstr "您可以在這裡建立一個新的安全性群組"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:9
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/edit_rules.html:6
+msgid "Edit Security Group Rules"
+msgstr "編輯安全性群組規則"
+
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:12
+#: dashboards/project/access_and_security/templates/access_and_security/security_groups/_edit_rules.html:19
+msgid "Add Rule"
+msgstr "新增規則"
+
+#: dashboards/project/containers/browsers.py:26
+msgid "Swift"
+msgstr "Swift"
+
+#: dashboards/project/containers/browsers.py:29
+#: dashboards/project/containers/tables.py:40
+msgid "Container"
+msgstr "容器"
+
+#: dashboards/project/containers/forms.py:39
+msgid "Slash is not an allowed character."
+msgstr "斜線符號不能被接受"
+
+#: dashboards/project/containers/forms.py:49
+#: dashboards/project/containers/tables.py:121
+msgid "Container Name"
+msgstr "容器名稱"
+
+#: dashboards/project/containers/forms.py:57
+msgid "Container created successfully."
+msgstr "容器已成功建立"
+
+#: dashboards/project/containers/forms.py:68
+msgid "Folder created successfully."
+msgstr "資料夾已成功建立。"
+
+#: dashboards/project/containers/forms.py:71
+msgid "Unable to create container."
+msgstr "無法建立容器"
+
+#: dashboards/project/containers/forms.py:79
+#: dashboards/project/containers/tables.py:253
+msgid "Object Name"
+msgstr "物件名稱"
+
+#: dashboards/project/containers/forms.py:81
+msgid "File"
+msgstr "檔案"
+
+#: dashboards/project/containers/forms.py:95
+msgid "Object was successfully uploaded."
+msgstr "物件已成功上傳"
+
+#: dashboards/project/containers/forms.py:98
+msgid "Unable to upload object."
+msgstr "無法上傳物件"
+
+#: dashboards/project/containers/forms.py:102
+msgid "Destination container"
+msgstr "目的地容器"
+
+#: dashboards/project/containers/forms.py:106
+msgid "Destination object name"
+msgstr "目的地物件名稱"
+
+#: dashboards/project/containers/forms.py:137
+#: dashboards/project/containers/forms.py:163
+msgid "Unable to copy object."
+msgstr "無法複製物件"
+
+#: dashboards/project/containers/forms.py:153
+#, python-format
+msgid "Copied \"%(orig)s\" to \"%(dest)s\" as \"%(new)s\"."
+msgstr "複製 \"%(orig)s\" 到 \"%(dest)s\" 成為 \"%(new)s\"。"
+
+#: dashboards/project/containers/panel.py:29
+#: dashboards/project/containers/tables.py:41
+#: dashboards/project/containers/tables.py:128
+#: dashboards/project/containers/templates/containers/index.html:7
+msgid "Containers"
+msgstr "容器"
+
+#: dashboards/project/containers/tables.py:62
+#: dashboards/project/containers/templates/containers/_create.html:7
+#: dashboards/project/containers/templates/containers/_create.html:22
+#: dashboards/project/containers/templates/containers/create.html:6
+msgid "Create Container"
+msgstr "建立容器"
+
+#: dashboards/project/containers/tables.py:69
+msgid "View Container"
+msgstr "檢視容器"
+
+#: dashboards/project/containers/tables.py:81
+#: dashboards/project/containers/templates/containers/_upload.html:23
+#: dashboards/project/containers/templates/containers/upload.html:3
+msgid "Upload Object"
+msgstr "上傳物件"
+
+#: dashboards/project/containers/tables.py:137
+#: dashboards/project/containers/tables.py:156
+msgid "Object"
+msgstr "物件"
+
+#: dashboards/project/containers/tables.py:138
+#: dashboards/project/containers/tables.py:157
+#: dashboards/project/containers/tables.py:263
+msgid "Objects"
+msgstr "物件"
+
+#: dashboards/project/containers/tables.py:149
+msgid "Folder"
+msgstr "資料夾"
+
+#: dashboards/project/containers/tables.py:150
+msgid "Folders"
+msgstr "資料夾"
+
+#: dashboards/project/containers/tables.py:163
+msgid "Copy"
+msgstr "複製"
+
+#: dashboards/project/containers/tables.py:176
+msgid "Download"
+msgstr "下載"
+
+#: dashboards/project/containers/tables.py:232
+msgid "Create Folder"
+msgstr "建立資料夾"
+
+#: dashboards/project/containers/views.py:53
+msgid "Unable to retrieve container list."
+msgstr "無法取得容器列表。"
+
+#: dashboards/project/containers/views.py:82
+msgid "Unable to retrieve object list."
+msgstr "無法取得物件列表。"
+
+#: dashboards/project/containers/views.py:166
+msgid "Unable to retrieve object."
+msgstr "無法取得物件。"
+
+#: dashboards/project/containers/views.py:200
+msgid "Unable to list containers."
+msgstr "無法列出容器。"
+
+#: dashboards/project/containers/templates/containers/_copy.html:7
+#: dashboards/project/containers/templates/containers/_copy.html:22
+#: dashboards/project/containers/templates/containers/copy.html:3
+#: dashboards/project/containers/templates/containers/copy.html:6
+msgid "Copy Object"
+msgstr "複製物件"
+
+#: dashboards/project/containers/templates/containers/_copy.html:17
+msgid ""
+"Make a new copy of an existing object to store in this or another container. "
+"You may also specify a path at which the new copy should live inside of the "
+"selected container."
+msgstr ""
+
+#: dashboards/project/containers/templates/containers/_create.html:17
+msgid ""
+"A container is a storage compartment for your data and provides a way for "
+"you to organize your data. You can think of a container as a folder in "
+"Windows &reg; or a directory in UNIX &reg;. The primary difference between a "
+"container and these other file system concepts is that containers cannot be "
+"nested. You can, however, create an unlimited number of containers within "
+"your account. Data must be stored in a container so you must have at least "
+"one container defined in your account prior to uploading data."
+msgstr ""
+"容器是資料的儲存分隔,提供一種分類管理資料的方法。您可以把容器想像成Windows "
+"&reg;中的資料夾或UNIX &reg;中的目錄。容器和其他檔案系統的主要差別是,容器裡面"
+"不能有其他容器。但是,您可以在您的帳戶建立無限個容器。資料必須儲存在容器裡,"
+"因此您必須在帳戶內建立至少一個容器,才能上傳資料。"
+
+#: dashboards/project/containers/templates/containers/_upload.html:8
+msgid "Upload Object To Container"
+msgstr "上傳物件到容器"
+
+#: dashboards/project/containers/templates/containers/_upload.html:18
+msgid ""
+"An object is the basic storage entity and any optional metadata that "
+"represents the files you store in the OpenStack Object Storage system. When "
+"you upload data to OpenStack Object Storage, the data is stored as-is (no "
+"compression or encryption) and consists of a location (container), the "
+"object's name, and any metadata consisting of key/value pairs."
+msgstr ""
+"物件是OpenStack物件儲存系統裡,用來代表所儲存的檔案加上相關的metadata組成的儲"
+"存基本單位。當您上傳資料到OpenStack物件儲存時,該資料是原封不動(沒有壓縮或加"
+"密)的被儲存,包含相關位置(容器),物件名稱,及相關的key/value metadata"
+
+#: dashboards/project/containers/templates/containers/upload.html:6
+msgid "Upload Objects"
+msgstr "上傳物件"
+
+#: dashboards/project/images_and_snapshots/panel.py:26
+msgid "Images & Snapshots"
+msgstr "映像 & 快照"
+
+#: dashboards/project/images_and_snapshots/views.py:63
+msgid "Unable to retrieve images."
+msgstr "無法取得映像。"
+
+#: dashboards/project/images_and_snapshots/views.py:74
+msgid "Unable to retrieve snapshots."
+msgstr "無法取得快照。"
+
+#: dashboards/project/images_and_snapshots/views.py:82
+#: dashboards/project/volumes/forms.py:65
+msgid "Unable to retrieve volume snapshots."
+msgstr "無法取得空間快照"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:42
+msgid "Image Location"
+msgstr "映像位置"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:43
+msgid "An external (HTTP) URL to load the image from."
+msgstr "用來載入映像的外部 (HTTP) URL。"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:46
+#: dashboards/project/images_and_snapshots/images/forms.py:130
+#: dashboards/project/images_and_snapshots/images/tables.py:126
+msgid "Format"
+msgstr "格式"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:50
+msgid "AKI - Amazon Kernel Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:53
+msgid "AMI - Amazon Machine Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:56
+msgid "ARI - Amazon Ramdisk Image"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/images/forms.py:59
+msgid "ISO - Optical Disk Image"
+msgstr "ISO - 光碟映像"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:61
+msgid "QCOW2 - QEMU Emulator"
+msgstr "QCOW2 - QEMU 模擬器"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:68
+msgid "Minimum Disk (GB)"
+msgstr "最小磁碟 (GB)"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:69
+#: dashboards/project/images_and_snapshots/images/forms.py:76
+msgid ""
+"The minimum disk size required to boot the image. If unspecified, this value "
+"defaults to 0 (no minimum)."
+msgstr ""
+"映像開機所需的最小磁碟容量。如果沒有指定,這個數值預設為 0 (沒有最小值)。"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:75
+msgid "Minimum Ram (MB)"
+msgstr "最小記憶體 (MB)"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:82
+#: dashboards/project/images_and_snapshots/images/forms.py:134
+#: dashboards/project/images_and_snapshots/images/tables.py:123
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:15
+msgid "Public"
+msgstr "公開"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:106
+#, python-format
+msgid "Your image %s has been queued for creation."
+msgstr "您的映像 %s 已經排程準備建立。"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:110
+msgid "Unable to create new image."
+msgstr "無法建立新的映像。"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:116
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:48
+msgid "Kernel ID"
+msgstr "核心 ID"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:121
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:52
+msgid "Ramdisk ID"
+msgstr "Ramdisk ID"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:126
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:44
+msgid "Architecture"
+msgstr "系統架構"
+
+#: dashboards/project/images_and_snapshots/images/forms.py:138
+#, python-format
+msgid "Unable to update image \"%s\"."
+msgstr "無法更新映像\"%s\"."
+
+#: dashboards/project/images_and_snapshots/images/forms.py:162
+msgid "Image was successfully updated."
+msgstr "映像已成功更新"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:34
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:33
+#: dashboards/project/instances/workflows.py:455
+msgid "Launch"
+msgstr "啟動"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:46
+#: dashboards/project/images_and_snapshots/images/tables.py:82
+#: dashboards/project/instances/workflows.py:168
+#: dashboards/project/instances/workflows.py:173
+msgid "Image"
+msgstr "映像"
+
+#: dashboards/project/images_and_snapshots/images/tables.py:61
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:31
+msgid "Create Image"
+msgstr "建立映像"
+
+#: dashboards/project/images_and_snapshots/images/tabs.py:38
+msgid "Unable to retrieve image details."
+msgstr "無法取得執行個體的詳細資料"
+
+#: dashboards/project/images_and_snapshots/images/views.py:61
+msgid "Unable to retrieve image."
+msgstr "無法取回映像。"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:37
+msgid "Instance ID"
+msgstr "執行個體ID"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:40
+#: dashboards/project/volumes/forms.py:193
+msgid "Snapshot Name"
+msgstr "快照名稱"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:50
+#, python-format
+msgid "Snapshot \"%(name)s\" created for instance \"%(inst)s\""
+msgstr "執行個體 \"%(inst)s\"的快照\"%(name)s\"已被建立"
+
+#: dashboards/project/images_and_snapshots/snapshots/forms.py:56
+msgid "Unable to create snapshot."
+msgstr "無法建立快照。"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:48
+#: dashboards/project/instances/workflows.py:107
+#: dashboards/project/instances/workflows.py:169
+msgid "Snapshot"
+msgstr "快照"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:49
+msgid "Snapshots"
+msgstr "快照"
+
+#: dashboards/project/images_and_snapshots/snapshots/tables.py:55
+msgid "Instance Snapshots"
+msgstr "執行個體快照"
+
+#: dashboards/project/images_and_snapshots/snapshots/views.py:53
+msgid "Unable to retrieve instance."
+msgstr "無法取得執行個體"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/index.html:6
+msgid "Images &amp; Snapshots"
+msgstr "映像 &amp; 快照"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:7
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:3
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/create.html:6
+msgid "Create An Image"
+msgstr "建立一個映像"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:18
+msgid "Specify an image to upload to the Image Service."
+msgstr "指定要上傳到映像服務的映像。"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:21
+msgid ""
+"Currently only images available via an HTTP URL are supported. The image "
+"location must be accessible to the Image Service. Compressed image binaries "
+"are supported (.zip and .tar.gz.)"
+msgstr ""
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:24
+msgid "Please note: "
+msgstr "請注意:"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_create.html:25
+#, fuzzy
+msgid ""
+"The Image Location field MUST be a valid and direct URL to the image binary. "
+"URLs that redirect or serve error pages will result in unusable images."
+msgstr ""
+"映像位置欄位必須是有效且直接指向映像檔案的 URL。重新導向式的 URL 或伺服錯誤頁"
+"面都會造成不穩定的映像。"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:3
+msgid "Image Overview"
+msgstr "映像總覽"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:6
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:7
+#: dashboards/project/instances/templates/instances/_detail_overview.html:6
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:6
+msgid "Info"
+msgstr "資訊"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:17
+msgid "Checksum"
+msgstr "校驗碼"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:19
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:39
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:28
+msgid "Created"
+msgstr "建立於"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:21
+msgid "Updated"
+msgstr "更新於"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:27
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:34
+#: dashboards/project/instances/templates/instances/_detail_overview.html:19
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:23
+msgid "Specs"
+msgstr "規格"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:32
+msgid "Container Format"
+msgstr "容器格式"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:34
+msgid "Disk Format"
+msgstr "磁碟格式"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:40
+msgid "Custom Properties"
+msgstr "專門屬性"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:56
+msgid "Euca2ools state"
+msgstr "Euca2ools狀態"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/_detail_overview.html:64
+msgid "Image Type"
+msgstr "映像類型"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/images/detail.html:4
+msgid "Image Detail "
+msgstr "映像詳細資料"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:8
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:23
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:3
+#: dashboards/project/instances/tables.py:179
+#: dashboards/project/volumes/tables.py:76
+msgid "Create Snapshot"
+msgstr "建立快照"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_create.html:18
+msgid "Snapshots preserve the disk state of a running instance."
+msgstr "快照可保存運作中的執行個體的磁碟內容狀態"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:20
+#: dashboards/project/instances/workflows.py:75
+#: dashboards/project/instances/workflows.py:110
+#: dashboards/project/instances/templates/instances/_detail_overview.html:93
+#: dashboards/project/volumes/tables.py:37
+#: dashboards/project/volumes/tables.py:182
+msgid "Volume"
+msgstr "容量"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/_detail_overview.html:38
+#: dashboards/project/instances/templates/instances/_detail_overview.html:29
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:11
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:12
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:27
+msgid "GB"
+msgstr "GB"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/create.html:6
+msgid "Create a Snapshot"
+msgstr "建立快照"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:3
+#, fuzzy
+msgid "Volume Snapshot Details"
+msgstr "容量快照"
+
+#: dashboards/project/images_and_snapshots/templates/images_and_snapshots/snapshots/detail.html:6
+#, fuzzy
+msgid "Volume Snapshot Detail"
+msgstr "容量快照"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:34
+#: dashboards/project/instances/workflows.py:76
+msgid "Volume Snapshot"
+msgstr "容量快照"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:35
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:85
+msgid "Volume Snapshots"
+msgstr "容量快照"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:43
+#: dashboards/project/volumes/tables.py:59
+#: dashboards/project/volumes/templates/volumes/_create.html:8
+#: dashboards/project/volumes/templates/volumes/_create.html:55
+msgid "Create Volume"
+msgstr "建立容量"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tables.py:80
+#: dashboards/project/volumes/forms.py:26
+msgid "Volume Name"
+msgstr "儲存區名稱"
+
+#: dashboards/project/images_and_snapshots/volume_snapshots/tabs.py:41
+#, fuzzy
+msgid "Unable to retrieve snapshot details."
+msgstr "無法取回連接埠詳細資料。"
+
+#: dashboards/project/instances/forms.py:45
+#, python-format
+msgid "Instance \"%s\" updated."
+msgstr "執行個體\"%s\"已更新"
+
+#: dashboards/project/instances/forms.py:50
+msgid "Unable to update instance."
+msgstr "無法更新執行個體"
+
+#: dashboards/project/instances/tables.py:67
+msgid "Terminate"
+msgstr "終止執行"
+
+#: dashboards/project/instances/tables.py:68
+msgid "Scheduled termination of"
+msgstr "已排程終止:"
+
+#: dashboards/project/instances/tables.py:87
+msgid "Reboot"
+msgstr "重啟"
+
+#: dashboards/project/instances/tables.py:88
+msgid "Rebooted"
+msgstr "已重啟"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Pause"
+msgstr "暫停"
+
+#: dashboards/project/instances/tables.py:104
+msgid "Unpause"
+msgstr "取消暫停"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Paused"
+msgstr "已暫停"
+
+#: dashboards/project/instances/tables.py:105
+msgid "Unpaused"
+msgstr "已取消暫停"
+
+#: dashboards/project/instances/tables.py:133
+msgid "Suspend"
+msgstr "休眠"
+
+#: dashboards/project/instances/tables.py:133
+msgid "Resume"
+msgstr "喚醒"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Suspended"
+msgstr "已休眠"
+
+#: dashboards/project/instances/tables.py:134
+msgid "Resumed"
+msgstr "已喚醒"
+
+#: dashboards/project/instances/tables.py:162
+#: dashboards/project/instances/workflows.py:454
+#: dashboards/project/instances/templates/instances/launch.html:3
+#: dashboards/project/instances/templates/instances/launch.html:6
+msgid "Launch Instance"
+msgstr "啟動執行個體"
+
+#: dashboards/project/instances/tables.py:169
+#: dashboards/project/instances/templates/instances/_update.html:7
+msgid "Edit Instance"
+msgstr "編輯執行個體"
+
+#: dashboards/project/instances/tables.py:189
+msgid "VNC Console"
+msgstr "VNC界面"
+
+#: dashboards/project/instances/tables.py:204
+msgid "View Log"
+msgstr "檢視記錄檔"
+
+#: dashboards/project/instances/tables.py:252
+#, python-format
+msgid "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s Disk"
+msgstr "%(name)s | %(RAM)s RAM | %(VCPU)s VCPU | %(disk)s 磁碟"
+
+#: dashboards/project/instances/tables.py:259
+#: dashboards/project/instances/tables.py:266
+msgid "Not available"
+msgstr "不存在"
+
+#: dashboards/project/instances/tabs.py:36
+msgid "Log"
+msgstr "記錄檔"
+
+#: dashboards/project/instances/tabs.py:48
+#: dashboards/project/instances/views.py:106
+#, python-format
+msgid "Unable to get log for instance \"%s\"."
+msgstr "無法取得執行個體\"%s\"的記錄檔。"
+
+#: dashboards/project/instances/tabs.py:55
+msgid "VNC"
+msgstr "VNC"
+
+#: dashboards/project/instances/tabs.py:70
+#: dashboards/project/instances/views.py:122
+#, python-format
+msgid "Unable to get VNC console for instance \"%s\"."
+msgstr "無法取得執行個體的VNC界面\"%s\"。"
+
+#: dashboards/project/instances/views.py:59
+msgid "Unable to retrieve instances."
+msgstr "無法取得執行個體。"
+
+#: dashboards/project/instances/views.py:144
+msgid "Unable to retrieve instance details."
+msgstr "無法取得執行個體的詳細資料"
+
+#: dashboards/project/instances/views.py:179
+#, python-format
+msgid "Unable to retrieve details for instance \"%s\"."
+msgstr "無法取得執行個體\"%s\"詳細資料。"
+
+#: dashboards/project/instances/workflows.py:53
+msgid "Project & User"
+msgstr "專案 & 使用者"
+
+#: dashboards/project/instances/workflows.py:66
+msgid "Don't boot from a volume."
+msgstr "不要從儲存區開機。"
+
+#: dashboards/project/instances/workflows.py:67
+msgid "Boot from volume."
+msgstr "從儲存區開機。"
+
+#: dashboards/project/instances/workflows.py:68
+msgid "Boot from volume snapshot (creates a new volume)."
+msgstr "從儲存區快照開機 (會建立一個新的儲存區)。"
+
+#: dashboards/project/instances/workflows.py:72
+#: dashboards/project/instances/workflows.py:90
+msgid "Volume Options"
+msgstr "儲存區選項"
+
+#: dashboards/project/instances/workflows.py:78
+#: dashboards/project/volumes/forms.py:126
+msgid "Device Name"
+msgstr "裝置名稱"
+
+#: dashboards/project/instances/workflows.py:81
+msgid "Volume mount point (e.g. 'vda' mounts at '/dev/vda')."
+msgstr "容量掛載點 (例如: ‘vda’掛載在‘/dev/vda’)"
+
+#: dashboards/project/instances/workflows.py:83
+msgid "Delete on Terminate"
+msgstr "終止執行時刪除"
+
+#: dashboards/project/instances/workflows.py:86
+msgid "Delete volume on instance terminate"
+msgstr "執行個體終止執行時刪除容量"
+
+#: dashboards/project/instances/workflows.py:100
+#, python-format
+msgid "Please choose a volume, or select %s."
+msgstr "請選擇一個儲存區,或是選擇 %s。"
+
+#: dashboards/project/instances/workflows.py:117
+msgid "Select Volume"
+msgstr "選擇容量"
+
+#: dashboards/project/instances/workflows.py:125
+msgid "Unable to retrieve list of volumes."
+msgstr "無法取回儲存區清單。"
+
+#: dashboards/project/instances/workflows.py:129
+msgid "Select Volume Snapshot"
+msgstr "選擇儲存區快照"
+
+#: dashboards/project/instances/workflows.py:138
+msgid "Unable to retrieve list of volume snapshots."
+msgstr "無法取回儲存區快照清單。"
+
+#: dashboards/project/instances/workflows.py:171
+msgid "Instance Source"
+msgstr "個體來源"
+
+#: dashboards/project/instances/workflows.py:174
+msgid "Instance Snapshot"
+msgstr "個體快照"
+
+#: dashboards/project/instances/workflows.py:178
+msgid "Size of image to launch."
+msgstr "啟動的映像大小。"
+
+#: dashboards/project/instances/workflows.py:179
+msgid "Instance Count"
+msgstr "執行個體數量"
+
+#: dashboards/project/instances/workflows.py:182
+msgid "Number of instances to launch."
+msgstr "要啟動的執行個體數量"
+
+#: dashboards/project/instances/workflows.py:185
+msgid "Details"
+msgstr "詳細資料"
+
+#: dashboards/project/instances/workflows.py:198
+msgid ""
+"There are no image sources available; you must first create an image before "
+"attempting to launch an instance."
+msgstr ""
+"沒有可用的映像來源;在執行一個個體之前您必須先建立一個要附加上去的映像。"
+
+#: dashboards/project/instances/workflows.py:203
+msgid "Please select an option for the instance source."
+msgstr "請選擇個體來源的選項。"
+
+#: dashboards/project/instances/workflows.py:212
+msgid ""
+"Launching multiple instances is only supported for images and instance "
+"snapshots."
+msgstr "執行多個實體只支援映像檔和個體快照。"
+
+#: dashboards/project/instances/workflows.py:229
+msgid "Unable to retrieve public images."
+msgstr "無法取回公開映像。"
+
+#: dashboards/project/instances/workflows.py:244
+msgid "Unable to retrieve images for the current project."
+msgstr "無法取回目前專案的映像。"
+
+#: dashboards/project/instances/workflows.py:267
+msgid "Select Image"
+msgstr "選擇映像"
+
+#: dashboards/project/instances/workflows.py:269
+msgid "No images available."
+msgstr "沒有映像可用。"
+
+#: dashboards/project/instances/workflows.py:278
+msgid "Select Instance Snapshot"
+msgstr "選擇個體快照"
+
+#: dashboards/project/instances/workflows.py:280
+msgid "No snapshots available."
+msgstr "沒有快照可用。"
+
+#: dashboards/project/instances/workflows.py:291
+msgid "Unable to retrieve instance flavors."
+msgstr "無法取得執行個體規格。"
+
+#: dashboards/project/instances/workflows.py:304 usage/base.py:114
+msgid "Unable to retrieve quota information."
+msgstr "無法取回限額資訊。"
+
+#: dashboards/project/instances/workflows.py:337
+msgid "Which keypair to use for authentication."
+msgstr "認證用的金鑰選擇"
+
+#: dashboards/project/instances/workflows.py:344
+msgid "Launch instance in these security groups."
+msgstr "在這些安全性群組中啟動執行個體"
+
+#: dashboards/project/instances/workflows.py:349
+msgid ""
+"Control access to your instance via keypairs, security groups, and other "
+"mechanisms."
+msgstr "透過金鑰、安全性群組和其他機制來控制如何存取您的個體。"
+
+#: dashboards/project/instances/workflows.py:359
+msgid "Unable to retrieve keypairs."
+msgstr "無法取得金鑰。"
+
+#: dashboards/project/instances/workflows.py:361
+msgid "Select a keypair"
+msgstr "選擇金鑰"
+
+#: dashboards/project/instances/workflows.py:363
+msgid "No keypairs available."
+msgstr "沒有可用的金鑰"
+
+#: dashboards/project/instances/workflows.py:372
+msgid "Unable to retrieve list of security groups"
+msgstr "無法取得安全性群組列表。"
+
+#: dashboards/project/instances/workflows.py:392
+msgid "Customization Script"
+msgstr "自訂命令稿"
+
+#: dashboards/project/instances/workflows.py:394
+msgid ""
+"A script or set of commands to be executed after the instance has been built "
+"(max 16kb)."
+msgstr "在個體建立後要執行的命令稿或一組指令 (最大 16kb)。"
+
+#: dashboards/project/instances/workflows.py:401
+msgid "Post-Creation"
+msgstr "Post-Creation"
+
+#: dashboards/project/instances/workflows.py:415
+msgid "Launch instance withthese networks"
+msgstr "執行這些網路的個體"
+
+#: dashboards/project/instances/workflows.py:419
+msgid "Networking"
+msgstr "網路"
+
+#: dashboards/project/instances/workflows.py:421
+msgid "Select networks for your instance."
+msgstr "選擇您的個體的網路。"
+
+#: dashboards/project/instances/workflows.py:433
+msgid "Unable to retrieve networks."
+msgstr "無法取回網路。"
+
+#: dashboards/project/instances/workflows.py:456
+#, python-format
+msgid "Launched %(count)s named \"%(name)s\"."
+msgstr "執行 %(count)s 名稱 \"%(name)s\"。"
+
+#: dashboards/project/instances/workflows.py:457
+#, python-format
+msgid "Unable to launch %(count)s named \"%(name)s\"."
+msgstr "無法執行 %(count)s 名稱 \"%(name)s\"。"
+
+#: dashboards/project/instances/workflows.py:470
+#, python-format
+msgid "%s instances"
+msgstr "%s 個體"
+
+#: dashboards/project/instances/workflows.py:473
+msgid "instance"
+msgstr "個體"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:4
+msgid "Instance Console Log"
+msgstr "個體主控臺紀錄"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:7
+msgid "Log Length"
+msgstr "紀錄長度"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:9
+msgid "Go"
+msgstr "開始"
+
+#: dashboards/project/instances/templates/instances/_detail_log.html:11
+msgid "View Full Log"
+msgstr "檢視完整記錄檔"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:3
+msgid "Instance Overview"
+msgstr "執行個體總覽"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:27
+msgid "VCPU"
+msgstr "虛擬處理器"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:28
+#: usage/tables.py:20
+msgid "Disk"
+msgstr "磁碟"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:34
+msgid "IP Addresses"
+msgstr "IP位址"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:59
+msgid "No rules defined."
+msgstr "沒有規則被制定"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:68
+msgid "Meta"
+msgstr "相關資料"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:71
+msgid "Key Name"
+msgstr "金鑰名稱"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:84
+msgid "Volumes Attached"
+msgstr "附加的儲存區"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:88
+#: dashboards/project/volumes/tables.py:167
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:38
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:45
+msgid "Attached To"
+msgstr "掛載到"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:90
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:42
+msgid "on"
+msgstr "在"
+
+#: dashboards/project/instances/templates/instances/_detail_overview.html:94
+msgid "No volumes attached."
+msgstr "沒有掛載的容量"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:3
+msgid "Instance VNC Console"
+msgstr "執行個體VNC界面"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid ""
+"If VNC console is not responding to keyboard input: click the grey status "
+"bar below."
+msgstr "如果VNC界面對鍵盤輸入沒有反應,點擊下面的灰色狀態條列"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:5
+msgid "Click here to show only VNC"
+msgstr "點選這裡只顯示 VNC"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:8
+msgid "VNC console is currently unavailabe. Please try again later."
+msgstr "VNC 主控臺目前無法使用。請稍後再試。"
+
+#: dashboards/project/instances/templates/instances/_detail_vnc.html:9
+msgid "Reload"
+msgstr "重新載入"
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:2
+msgid ""
+"You can customize your instance after it's launched using the options "
+"available here."
+msgstr "您可以在您的個體使用這裡的選項執行後再自訂它。"
+
+#: dashboards/project/instances/templates/instances/_launch_customize_help.html:3
+msgid ""
+"The \"Customization Script\" field is analogous to \"User Data\" in other "
+"systems."
+msgstr "「自訂命令稿」欄位類似於其他系中的「使用者資料」。"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:3
+msgid "Specify the details for launching an instance."
+msgstr "指定執行一個實體時的詳細資料。"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:4
+msgid ""
+"The chart below shows the resources used by this project in relation to the "
+"project's quotas."
+msgstr "下列圖表顯示了這個專案與專案的限額之間的資源。"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:6
+msgid "Flavor Details"
+msgstr ""
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:13
+msgid "Total Disk"
+msgstr "磁碟總計"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:14
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+msgid "MB"
+msgstr "MB"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:21
+msgid "Number of Instances"
+msgstr "個體的數量"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:29
+msgid "Number of VCPUs"
+msgstr "虛擬處理器的數量"
+
+#: dashboards/project/instances/templates/instances/_launch_details_help.html:37
+#, fuzzy
+msgid "Total RAM"
+msgstr "總記憶體"
+
+#: dashboards/project/instances/templates/instances/_launch_volumes_help.html:3
+msgid ""
+"An instance can be launched with varying types of attached storage. You may "
+"select from those options here."
+msgstr "實體可以附加各種類型的儲存裝置來執行。您可以從這裡選擇那些選項。"
+
+#: dashboards/project/instances/templates/instances/_update.html:17
+msgid "You may update the editable properties of your instance here."
+msgstr "您可以在這裡更新您實體的可編輯屬性。"
+
+#: dashboards/project/instances/templates/instances/detail.html:3
+msgid "Instance Detail"
+msgstr "執行個體詳述"
+
+#: dashboards/project/instances/templates/instances/update.html:3
+#: dashboards/project/instances/templates/instances/update.html:6
+msgid "Update Instance"
+msgstr "更新執行個體"
+
+#: dashboards/project/networks/tables.py:81
+msgid "Add Subnet"
+msgstr "加入子網路"
+
+#: dashboards/project/networks/views.py:86
+msgid "Unable to retrieve network details."
+msgstr "無法取回網路詳細資料。"
+
+#: dashboards/project/networks/workflows.py:37
+msgid "Network Name (optional)"
+msgstr "網路名稱 (選擇性)"
+
+#: dashboards/project/networks/workflows.py:42
+msgid ""
+"From here you can create a new network.\n"
+"In addition a subnet associated with the network can be created in the next "
+"panel."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:56
+msgid "Subnet Name (optional)"
+msgstr "子網路名稱 (選擇性)"
+
+#: dashboards/project/networks/workflows.py:61
+#: dashboards/project/networks/subnets/forms.py:48
+msgid "Network address in CIDR format (e.g. 192.168.0.0/24)"
+msgstr "網路位址 CIDR 格式 (例如 192.168.0.0/24)"
+
+#: dashboards/project/networks/workflows.py:67
+msgid "Gateway IP (optional)"
+msgstr "閘道器 IP (選擇性)"
+
+#: dashboards/project/networks/workflows.py:70
+#: dashboards/project/networks/subnets/forms.py:57
+#: dashboards/project/networks/subnets/forms.py:107
+msgid "IP address of Gateway (e.g. 192.168.0.1)"
+msgstr "閘道器的 IP 位址 (例如 192.168.0.1)"
+
+#: dashboards/project/networks/workflows.py:77
+msgid ""
+"You can create a subnet associated with the new network, in which case "
+"\"Network Address\" must be specified. If you wish to create a network "
+"WITHOUT a subnet, uncheck the \"Create Subnet\" checkbox."
+msgstr ""
+
+#: dashboards/project/networks/workflows.py:89
+msgid "Specify \"Network Address\" or clear \"Create Subnet\" checkbox."
+msgstr "指定「網路位址」或取消核取「建立子網路」核取方塊。"
+
+#: dashboards/project/networks/workflows.py:94
+#: dashboards/project/networks/subnets/forms.py:70
+msgid "Network Address and IP version are inconsistent."
+msgstr "網路位址與 IP 版本不一致。"
+
+#: dashboards/project/networks/workflows.py:98
+#: dashboards/project/networks/subnets/forms.py:74
+#: dashboards/project/networks/subnets/forms.py:119
+msgid "Gateway IP and IP version are inconsistent."
+msgstr "閘道器 IP 與 IP 版本不一致。"
+
+#: dashboards/project/networks/workflows.py:112
+msgid "Create"
+msgstr "建立"
+
+#: dashboards/project/networks/workflows.py:113
+#, python-format
+msgid "Created network \"%s\"."
+msgstr "建立網路 \"%s\"。"
+
+#: dashboards/project/networks/workflows.py:114
+#, python-format
+msgid "Unable to create network \"%s\"."
+msgstr "無法建立網路 \"%s\"。"
+
+#: dashboards/project/networks/workflows.py:130
+#, python-format
+msgid "Network \"%s\" was successfully created."
+msgstr "網路 \"%s\" 已成功建立。"
+
+#: dashboards/project/networks/workflows.py:133
+#, python-format
+msgid "Failed to create network \"%s\"."
+msgstr "無法建立網路 \"%s\"。"
+
+#: dashboards/project/networks/workflows.py:152
+#, python-format
+msgid "Subnet \"%s\" was successfully created."
+msgstr "子網路 \"%s\" 已成功建立。"
+
+#: dashboards/project/networks/workflows.py:155
+#, python-format
+msgid "Failed to create subnet \"%(sub)s\" for network \"%(net)s\"."
+msgstr "無法建立網路 \"%(net)s\" 的子網路 \"%(sub)s\"。"
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Attached"
+msgstr "已附加"
+
+#: dashboards/project/networks/ports/tables.py:35
+msgid "Detached"
+msgstr "已分離"
+
+#: dashboards/project/networks/subnets/forms.py:85
+#, python-format
+msgid "Subnet %s was successfully created."
+msgstr "子網路 %s 已成功建立。"
+
+#: dashboards/project/networks/subnets/forms.py:90
+#, python-format
+msgid "Failed to create subnet %s"
+msgstr "無法建立子網路 %s"
+
+#: dashboards/project/networks/subnets/forms.py:131
+#, python-format
+msgid "Subnet %s was successfully updated."
+msgstr "子網路 %s 已成功更新。"
+
+#: dashboards/project/networks/subnets/forms.py:136
+#, python-format
+msgid "Failed to update subnet %s"
+msgstr "無法更新子網路 %s"
+
+#: dashboards/project/networks/subnets/tabs.py:42
+msgid "Unable to retrieve subnet details."
+msgstr "無法取回子網路詳細資料。"
+
+#: dashboards/project/networks/templates/networks/_detail_overview.html:3
+msgid "Network Overview"
+msgstr "網路總覽"
+
+#: dashboards/project/networks/templates/networks/detail.html:6
+msgid "Network Detail: "
+msgstr "網路詳細資料:"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:3
+msgid "Port Overview"
+msgstr "連接埠總覽"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:17
+msgid "Fixed IP"
+msgstr "固定 IP"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:21
+msgid "IP address:"
+msgstr "IP 位址:"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:22
+msgid "Subnet ID"
+msgstr "子網路 ID"
+
+#: dashboards/project/networks/templates/networks/ports/_detail_overview.html:28
+msgid "Mac Address"
+msgstr "Mac 位址"
+
+#: dashboards/project/networks/templates/networks/ports/detail.html:3
+#: dashboards/project/networks/templates/networks/ports/detail.html:6
+msgid "Port Detail"
+msgstr "連接埠詳細資料"
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:3
+msgid "Subnet Overview"
+msgstr "子網路總覽"
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:21
+msgid "IP allocation pool"
+msgstr ""
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:24
+msgid "Start"
+msgstr "開頭"
+
+#: dashboards/project/networks/templates/networks/subnets/_detail_overview.html:25
+msgid " - End"
+msgstr " - 結尾"
+
+#: dashboards/project/networks/templates/networks/subnets/detail.html:3
+#: dashboards/project/networks/templates/networks/subnets/detail.html:6
+msgid "Subnet Detail"
+msgstr "子網路詳細資料"
+
+#: dashboards/project/volumes/forms.py:29
+msgid "Size (GB)"
+msgstr "容量 (GB)"
+
+#: dashboards/project/volumes/forms.py:30
+msgid "Use snapshot as a source"
+msgstr "使用快照作為來源"
+
+#: dashboards/project/volumes/forms.py:49
+#, python-format
+msgid "Volume size must be equal to or greater than the snapshot size (%sGB)"
+msgstr "儲存區容量必須大於或等於快照容量 (%sGB)"
+
+#: dashboards/project/volumes/forms.py:54
+msgid "Unable to load the specified snapshot."
+msgstr "無法載入指定的快照。"
+
+#: dashboards/project/volumes/forms.py:59
+msgid "Choose a snapshot"
+msgstr "選擇一個快照"
+
+#: dashboards/project/volumes/forms.py:83
+#, python-format
+msgid "The volume size cannot be less than the snapshot size (%sGB)"
+msgstr "儲存區容量不能大於快照容量 (%sGB)"
+
+#: dashboards/project/volumes/forms.py:92
+#, python-format
+msgid ""
+"A volume of %(req)iGB cannot be created as you only have %(avail)iGB of your "
+"quota available."
+msgstr "不能建立 %(req)iGB 的儲存區,因為您只剩下 %(avail)iGB 的限額。"
+
+#: dashboards/project/volumes/forms.py:99
+msgid "You are already using all of your available volumes."
+msgstr "您已經使用了所有可用的儲存區。"
+
+#: dashboards/project/volumes/forms.py:115
+msgid "Unable to create volume."
+msgstr "無法建立儲存區。"
+
+#: dashboards/project/volumes/forms.py:123
+msgid "Attach to Instance"
+msgstr "附加到個體"
+
+#: dashboards/project/volumes/forms.py:124
+msgid "Select an instance to attach to."
+msgstr "選擇掛載的執行個體"
+
+#: dashboards/project/volumes/forms.py:168
+msgid "Unknown instance (None)"
+msgstr "不明的個體 (沒有)"
+
+#: dashboards/project/volumes/forms.py:179
+#, python-format
+msgid "Attaching volume %(vol)s to instance %(inst)s on %(dev)s."
+msgstr "將儲存區 %(vol)s 附加到個體 %(inst)s 於 %(dev)s。"
+
+#: dashboards/project/volumes/forms.py:188
+msgid "Unable to attach volume."
+msgstr "無法附加儲存區。"
+
+#: dashboards/project/volumes/forms.py:212
+#, python-format
+msgid "Creating volume snapshot \"%s\""
+msgstr "建立容量快照\"%s\""
+
+#: dashboards/project/volumes/forms.py:218
+msgid "Unable to create volume snapshot."
+msgstr "無法建立儲存區快照。"
+
+#: dashboards/project/volumes/tables.py:46
+#, fuzzy, python-format
+msgid "Unable to delete volume \"%s\". One or more snapshots depend on it."
+msgstr "無法取得空間快照"
+
+#: dashboards/project/volumes/tables.py:66
+msgid "Edit Attachments"
+msgstr "編輯掛載"
+
+#: dashboards/project/volumes/tables.py:93
+#, python-format
+msgid "%sGB"
+msgstr "%sGB"
+
+#: dashboards/project/volumes/tables.py:106
+#: dashboards/project/volumes/views.py:149
+msgid "Unable to retrieve attachment information."
+msgstr "無法取回附加資訊。"
+
+#: dashboards/project/volumes/tables.py:123
+#, python-format
+msgid "Attached to %(instance)s on %(dev)s"
+msgstr "附加到 %(instance)s 於 %(dev)s"
+
+#: dashboards/project/volumes/tables.py:180
+msgid "Detach"
+msgstr "卸載"
+
+#: dashboards/project/volumes/tables.py:181
+msgid "Detaching"
+msgstr "分離"
+
+#: dashboards/project/volumes/tables.py:216
+#, python-format
+msgid "%(dev)s on instance %(instance_name)s"
+msgstr "%(dev)s 於個體 %(instance_name)s"
+
+#: dashboards/project/volumes/tabs.py:42
+msgid "Unable to retrieve volume details."
+msgstr "無法取得容量快照"
+
+#: dashboards/project/volumes/views.py:50
+msgid "Unable to retrieve volume list."
+msgstr "無法取回儲存區清單。"
+
+#: dashboards/project/volumes/views.py:58
+msgid "Unable to retrieve volume/instance attachment information"
+msgstr "無法取回儲存區/個體附加資訊"
+
+#: dashboards/project/volumes/views.py:130
+#: dashboards/project/volumes/views.py:140
+msgid "Unable to retrieve volume information."
+msgstr "無法取得容量資訊"
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:9
+#: dashboards/project/volumes/templates/volumes/attach.html:6
+msgid "Manage Volume Attachments"
+msgstr "管理容量掛載"
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:13
+msgid "Attach To Instance"
+msgstr "掛載到執行個體"
+
+#: dashboards/project/volumes/templates/volumes/_attach.html:22
+msgid "Attach Volume"
+msgstr "掛載容量"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:20
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:18
+msgid "Volumes are block devices that can be attached to instances."
+msgstr "容量是可以掛載到執行個體的分塊磁碟裝置"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:22
+msgid "Volume Quotas"
+msgstr "儲存區限額"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:25
+msgid "Total Gigabytes"
+msgstr "總 GB 數"
+
+#: dashboards/project/volumes/templates/volumes/_create.html:34
+msgid "Number of Volumes"
+msgstr "儲存區數量"
+
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:8
+#: dashboards/project/volumes/templates/volumes/_create_snapshot.html:23
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:3
+msgid "Create Volume Snapshot"
+msgstr "建立容量快照"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:3
+msgid "Volume Overview"
+msgstr "容量總覽"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:34
+msgid "Attachments"
+msgstr "掛載"
+
+#: dashboards/project/volumes/templates/volumes/_detail_overview.html:46
+msgid "Not attached"
+msgstr "沒有掛載"
+
+#: dashboards/project/volumes/templates/volumes/create.html:6
+msgid "Create a Volume"
+msgstr "建立容量"
+
+#: dashboards/project/volumes/templates/volumes/create_snapshot.html:6
+msgid "Create a Volume Snapshot"
+msgstr "建立容量快照"
+
+#: dashboards/settings/dashboard.py:24 templates/_header.html:4
+msgid "Settings"
+msgstr "設定"
+
+#: dashboards/settings/ec2/forms.py:36 dashboards/settings/project/forms.py:36
+msgid "Select a Project"
+msgstr "選擇專案"
+
+#: dashboards/settings/ec2/forms.py:46
+msgid "Unable to retrieve tenant list."
+msgstr "無法取得租戶列表"
+
+#: dashboards/settings/ec2/forms.py:88
+msgid "Unable to fetch EC2 credentials."
+msgstr "無法讀取EC2憑證資料"
+
+#: dashboards/settings/ec2/forms.py:101
+#, python-format
+msgid "Error writing zipfile: %(exc)s"
+msgstr "寫入壓縮檔錯誤: %(exc)s"
+
+#: dashboards/settings/ec2/panel.py:25
+msgid "EC2 Credentials"
+msgstr "EC2憑證資料"
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:8
+#: dashboards/settings/ec2/templates/ec2/download_form.html:23
+#: dashboards/settings/ec2/templates/ec2/index.html:3
+#: dashboards/settings/ec2/templates/ec2/index.html:6
+msgid "Download EC2 Credentials"
+msgstr "下載EC2憑證資料"
+
+#: dashboards/settings/ec2/templates/ec2/download_form.html:18
+msgid ""
+"Clicking \"Download EC2 Credentials\" will download a zip file which "
+"includes an rc file with your access/secret keys, as well as your x509 "
+"private key and certificate."
+msgstr ""
+"點擊\"下載EC2認證憑據資料\"會下載一個壓縮檔,裡面含有您的x509私鑰和憑證"
+
+#: dashboards/settings/project/forms.py:71
+#, python-format
+msgid "Error Downloading RC File: %s"
+msgstr "RC檔下載錯誤: %s"
+
+#: dashboards/settings/project/panel.py:25
+#: dashboards/settings/project/templates/project/_openrc.html:8
+#: dashboards/settings/project/templates/project/settings.html:3
+#: dashboards/settings/project/templates/project/settings.html:6
+msgid "OpenStack API"
+msgstr "OpenStack API"
+
+#: dashboards/settings/project/tables.py:27
+msgid "Service Name"
+msgstr "服務名稱"
+
+#: dashboards/settings/project/tables.py:29
+msgid "Service Endpoint"
+msgstr "服務端點"
+
+#: dashboards/settings/project/tables.py:33
+msgid "API Endpoints"
+msgstr "API 端點"
+
+#: dashboards/settings/project/templates/project/_openrc.html:15
+msgid "Download OpenStack RC File"
+msgstr "下載OpenStack RC檔"
+
+#: dashboards/settings/project/templates/project/_openrc.html:25
+msgid ""
+"Download the RC file for the selected project, then type \"source openrc\" "
+"in the terminal to configure your environment to communicate with OpenStack."
+msgstr ""
+"下載所選擇專案的RC檔案後,在終端輸入\"source openrc\"來設置您的環境,以便和"
+"OpenStack做連線溝通。"
+
+#: dashboards/settings/project/templates/project/_openrc.html:30
+msgid "Download RC File"
+msgstr "下載RC檔"
+
+#: dashboards/settings/user/forms.py:57
+msgid "Settings saved."
+msgstr "設定值已儲存。"
+
+#: dashboards/settings/user/panel.py:25
+#: dashboards/settings/user/templates/user/_settings.html:8
+#: dashboards/settings/user/templates/user/settings.html:3
+#: dashboards/settings/user/templates/user/settings.html:6
+msgid "User Settings"
+msgstr "使用者設定"
+
+#: dashboards/settings/user/templates/user/_settings.html:18
+msgid "From here you can modify dashboard settings for your user."
+msgstr ""
+
#: templates/403.html:4 templates/403.html.py:9
msgid "Forbidden"
msgstr "禁止"
@@ -84,10 +3263,6 @@ msgstr "禁止"
msgid "Home"
msgstr "主頁"
-#: templates/403.html:24 templates/404.html:23 templates/500.html:23
-msgid "Projects"
-msgstr "專案"
-
#: templates/404.html:4
msgid "Page Not Found"
msgstr "頁面不存在"
@@ -109,3 +3284,47 @@ msgid ""
"An unexpected error occurred while processing your request. Please try your "
"request again."
msgstr "處理過程中發生無法預期的錯誤。請再嘗試。"
+
+#: templates/_header.html:3
+msgid "Logged in as"
+msgstr "登入為"
+
+#: templates/_header.html:6
+msgid "Help"
+msgstr "求助"
+
+#: templates/_header.html:8
+msgid "Sign Out"
+msgstr "登出"
+
+#: test/settings.py:50
+msgid "Password must be between 8 and 18 characters."
+msgstr "密碼必須介於 8 到 18 個字元之間。"
+
+#: usage/base.py:97
+msgid "Unable to retrieve usage information."
+msgstr "無法取得使用量資訊"
+
+#: usage/base.py:100
+msgid "You are viewing data for the future, which may or may not exist."
+msgstr "您正在查看未來的資料,它可能並不存在"
+
+#: usage/tables.py:11
+msgid "Download CSV Summary"
+msgstr "下載CSV摘要"
+
+#: usage/tables.py:25
+msgid "VCPU Hours"
+msgstr "虛擬處理器時數"
+
+#: usage/tables.py:32
+msgid "Disk GB Hours"
+msgstr "磁碟GB時數"
+
+#: usage/tables.py:40 usage/tables.py:68
+msgid "Usage Summary"
+msgstr "使用量摘要"
+
+#: usage/tables.py:60
+msgid "Uptime"
+msgstr "上機時間"
diff --git a/openstack_dashboard/openstack/__init__.py b/openstack_dashboard/openstack/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/openstack/__init__.py
diff --git a/openstack_dashboard/openstack/common/__init__.py b/openstack_dashboard/openstack/common/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/openstack/common/__init__.py
diff --git a/openstack_dashboard/openstack/common/setup.py b/openstack_dashboard/openstack/common/setup.py
new file mode 100644
index 000000000..79b5a62bc
--- /dev/null
+++ b/openstack_dashboard/openstack/common/setup.py
@@ -0,0 +1,200 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 OpenStack LLC.
+# All Rights Reserved.
+#
+# 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.
+
+"""
+Utilities with minimum-depends for use in setup.py
+"""
+
+import os
+import re
+import subprocess
+
+from setuptools.command import sdist
+
+
+def parse_mailmap(mailmap='.mailmap'):
+ mapping = {}
+ if os.path.exists(mailmap):
+ fp = open(mailmap, 'r')
+ for l in fp:
+ l = l.strip()
+ if not l.startswith('#') and ' ' in l:
+ canonical_email, alias = [x for x in l.split(' ')
+ if x.startswith('<')]
+ mapping[alias] = canonical_email
+ return mapping
+
+
+def canonicalize_emails(changelog, mapping):
+ """Takes in a string and an email alias mapping and replaces all
+ instances of the aliases in the string with their real email.
+ """
+ for alias, email in mapping.iteritems():
+ changelog = changelog.replace(alias, email)
+ return changelog
+
+
+# Get requirements from the first file that exists
+def get_reqs_from_files(requirements_files):
+ reqs_in = []
+ for requirements_file in requirements_files:
+ if os.path.exists(requirements_file):
+ return open(requirements_file, 'r').read().split('\n')
+ return []
+
+
+def parse_requirements(requirements_files=['requirements.txt',
+ 'tools/pip-requires']):
+ requirements = []
+ for line in get_reqs_from_files(requirements_files):
+ # For the requirements list, we need to inject only the portion
+ # after egg= so that distutils knows the package it's looking for
+ # such as:
+ # -e git://github.com/openstack/nova/master#egg=nova
+ if re.match(r'\s*-e\s+', line):
+ requirements.append(re.sub(r'\s*-e\s+.*#egg=(.*)$', r'\1',
+ line))
+ # such as:
+ # http://github.com/openstack/nova/zipball/master#egg=nova
+ elif re.match(r'\s*https?:', line):
+ requirements.append(re.sub(r'\s*https?:.*#egg=(.*)$', r'\1',
+ line))
+ # -f lines are for index locations, and don't get used here
+ elif re.match(r'\s*-f\s+', line):
+ pass
+ else:
+ requirements.append(line)
+
+ return requirements
+
+
+def parse_dependency_links(requirements_files=['requirements.txt',
+ 'tools/pip-requires']):
+ dependency_links = []
+ # dependency_links inject alternate locations to find packages listed
+ # in requirements
+ for line in get_reqs_from_files(requirements_files):
+ # skip comments and blank lines
+ if re.match(r'(\s*#)|(\s*$)', line):
+ continue
+ # lines with -e or -f need the whole line, minus the flag
+ if re.match(r'\s*-[ef]\s+', line):
+ dependency_links.append(re.sub(r'\s*-[ef]\s+', '', line))
+ # lines that are only urls can go in unmolested
+ elif re.match(r'\s*https?:', line):
+ dependency_links.append(line)
+ return dependency_links
+
+
+def write_requirements():
+ venv = os.environ.get('VIRTUAL_ENV', None)
+ if venv is not None:
+ with open("requirements.txt", "w") as req_file:
+ output = subprocess.Popen(["pip", "-E", venv, "freeze", "-l"],
+ stdout=subprocess.PIPE)
+ requirements = output.communicate()[0].strip()
+ req_file.write(requirements)
+
+
+def _run_shell_command(cmd):
+ output = subprocess.Popen(["/bin/sh", "-c", cmd],
+ stdout=subprocess.PIPE)
+ return output.communicate()[0].strip()
+
+
+def write_vcsversion(location):
+ """Produce a vcsversion dict that mimics the old one produced by bzr.
+ """
+ if os.path.isdir('.git'):
+ branch_nick_cmd = 'git branch | grep -Ei "\* (.*)" | cut -f2 -d" "'
+ branch_nick = _run_shell_command(branch_nick_cmd)
+ revid_cmd = "git rev-parse HEAD"
+ revid = _run_shell_command(revid_cmd).split()[0]
+ revno_cmd = "git log --oneline | wc -l"
+ revno = _run_shell_command(revno_cmd)
+ with open(location, 'w') as version_file:
+ version_file.write("""
+# This file is automatically generated by setup.py, So don't edit it. :)
+version_info = {
+ 'branch_nick': '%s',
+ 'revision_id': '%s',
+ 'revno': %s
+}
+""" % (branch_nick, revid, revno))
+
+
+def write_git_changelog():
+ """Write a changelog based on the git changelog."""
+ if os.path.isdir('.git'):
+ git_log_cmd = 'git log --stat'
+ changelog = _run_shell_command(git_log_cmd)
+ mailmap = parse_mailmap()
+ with open("ChangeLog", "w") as changelog_file:
+ changelog_file.write(canonicalize_emails(changelog, mailmap))
+
+
+def generate_authors():
+ """Create AUTHORS file using git commits."""
+ jenkins_email = 'jenkins@review.openstack.org'
+ old_authors = 'AUTHORS.in'
+ new_authors = 'AUTHORS'
+ if os.path.isdir('.git'):
+ # don't include jenkins email address in AUTHORS file
+ git_log_cmd = ("git log --format='%aN <%aE>' | sort -u | "
+ "grep -v " + jenkins_email)
+ changelog = _run_shell_command(git_log_cmd)
+ mailmap = parse_mailmap()
+ with open(new_authors, 'w') as new_authors_fh:
+ new_authors_fh.write(canonicalize_emails(changelog, mailmap))
+ if os.path.exists(old_authors):
+ with open(old_authors, "r") as old_authors_fh:
+ new_authors_fh.write('\n' + old_authors_fh.read())
+
+
+def get_cmdclass():
+ """Return dict of commands to run from setup.py."""
+
+ cmdclass = dict()
+
+ class LocalSDist(sdist.sdist):
+ """Builds the ChangeLog and Authors files from VC first."""
+
+ def run(self):
+ write_git_changelog()
+ generate_authors()
+ # sdist.sdist is an old style class, can't use super()
+ sdist.sdist.run(self)
+
+ cmdclass['sdist'] = LocalSDist
+
+ # If Sphinx is installed on the box running setup.py,
+ # enable setup.py to build the documentation, otherwise,
+ # just ignore it
+ try:
+ from sphinx.setup_command import BuildDoc
+
+ class LocalBuildDoc(BuildDoc):
+ def run(self):
+ for builder in ['html', 'man']:
+ self.builder = builder
+ self.finalize_options()
+ BuildDoc.run(self)
+ cmdclass['build_sphinx'] = LocalBuildDoc
+ except ImportError:
+ pass
+
+ return cmdclass
diff --git a/openstack_dashboard/settings.py b/openstack_dashboard/settings.py
index 5c8354391..b0b271811 100644
--- a/openstack_dashboard/settings.py
+++ b/openstack_dashboard/settings.py
@@ -53,7 +53,7 @@ ROOT_URLCONF = 'openstack_dashboard.urls'
HORIZON_CONFIG = {
'dashboards': ('project', 'admin', 'settings',),
'default_dashboard': 'project',
- 'user_home': 'horizon.views.base.get_user_home',
+ 'user_home': 'openstack_dashboard.views.get_user_home',
'ajax_queue_limit': 10,
'help_url': "http://docs.openstack.org",
'exceptions': {'recoverable': exceptions.RECOVERABLE,
@@ -80,6 +80,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.static',
'django.contrib.messages.context_processors.messages',
'horizon.context_processors.horizon',
+ 'openstack_dashboard.context_processors.openstack',
)
TEMPLATE_LOADERS = (
@@ -121,9 +122,9 @@ INSTALLED_APPS = (
'django.contrib.humanize',
'compressor',
'horizon',
- 'horizon.dashboards.project',
- 'horizon.dashboards.admin',
- 'horizon.dashboards.settings',
+ 'openstack_dashboard.dashboards.project',
+ 'openstack_dashboard.dashboards.admin',
+ 'openstack_dashboard.dashboards.settings',
'openstack_auth',
)
diff --git a/openstack_dashboard/templates/_header.html b/openstack_dashboard/templates/_header.html
new file mode 100644
index 000000000..9a85bf54a
--- /dev/null
+++ b/openstack_dashboard/templates/_header.html
@@ -0,0 +1,10 @@
+{% load i18n %}
+<div id="user_info" class="pull-right">
+ <span>{% trans "Logged in as" %}: {{ request.user.username }}</span>
+ <a href="{% url horizon:settings:user:index %}">{% trans "Settings" %}</a>
+ {% if HORIZON_CONFIG.help_url %}
+ <a href="{{ HORIZON_CONFIG.help_url }}" target="_new">{% trans "Help" %}</a>
+ {% endif %}
+ <a href="{% url logout %}">{% trans "Sign Out" %}</a>
+ {% include "horizon/common/_region_selector.html" %}
+</div>
diff --git a/openstack_dashboard/test/api_tests/__init__.py b/openstack_dashboard/test/api_tests/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/test/api_tests/__init__.py
diff --git a/openstack_dashboard/test/api_tests/base_tests.py b/openstack_dashboard/test/api_tests/base_tests.py
new file mode 100644
index 000000000..6ff5f138d
--- /dev/null
+++ b/openstack_dashboard/test/api_tests/base_tests.py
@@ -0,0 +1,149 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 horizon import exceptions
+
+from openstack_dashboard.test import helpers as test
+from openstack_dashboard.api import base as api_base
+
+
+class APIResource(api_base.APIResourceWrapper):
+ """ Simple APIResource for testing """
+ _attrs = ['foo', 'bar', 'baz']
+
+ @staticmethod
+ def get_instance(innerObject=None):
+ if innerObject is None:
+
+ class InnerAPIResource(object):
+ pass
+
+ innerObject = InnerAPIResource()
+ innerObject.foo = 'foo'
+ innerObject.bar = 'bar'
+ return APIResource(innerObject)
+
+
+class APIDict(api_base.APIDictWrapper):
+ """ Simple APIDict for testing """
+ _attrs = ['foo', 'bar', 'baz']
+
+ @staticmethod
+ def get_instance(innerDict=None):
+ if innerDict is None:
+ innerDict = {'foo': 'foo',
+ 'bar': 'bar'}
+ return APIDict(innerDict)
+
+
+# Wrapper classes that only define _attrs don't need extra testing.
+class APIResourceWrapperTests(test.TestCase):
+ def test_get_attribute(self):
+ resource = APIResource.get_instance()
+ self.assertEqual(resource.foo, 'foo')
+
+ def test_get_invalid_attribute(self):
+ resource = APIResource.get_instance()
+ self.assertNotIn('missing', resource._attrs,
+ msg="Test assumption broken. Find new missing attribute")
+ with self.assertRaises(AttributeError):
+ resource.missing
+
+ def test_get_inner_missing_attribute(self):
+ resource = APIResource.get_instance()
+ with self.assertRaises(AttributeError):
+ resource.baz
+
+
+class APIDictWrapperTests(test.TestCase):
+ # APIDict allows for both attribute access and dictionary style [element]
+ # style access. Test both
+ def test_get_item(self):
+ resource = APIDict.get_instance()
+ self.assertEqual(resource.foo, 'foo')
+ self.assertEqual(resource['foo'], 'foo')
+
+ def test_get_invalid_item(self):
+ resource = APIDict.get_instance()
+ self.assertNotIn('missing', resource._attrs,
+ msg="Test assumption broken. Find new missing attribute")
+ with self.assertRaises(AttributeError):
+ resource.missing
+ with self.assertRaises(KeyError):
+ resource['missing']
+
+ def test_get_inner_missing_attribute(self):
+ resource = APIDict.get_instance()
+ with self.assertRaises(AttributeError):
+ resource.baz
+ with self.assertRaises(KeyError):
+ resource['baz']
+
+ def test_get_with_default(self):
+ resource = APIDict.get_instance()
+
+ self.assertEqual(resource.get('foo'), 'foo')
+
+ self.assertIsNone(resource.get('baz'))
+
+ self.assertEqual('retValue', resource.get('baz', 'retValue'))
+
+
+class ApiHelperTests(test.TestCase):
+ """ Tests for functions that don't use one of the api objects """
+
+ def test_url_for(self):
+ url = api_base.url_for(self.request, 'image')
+ self.assertEqual(url, 'http://public.glance.example.com:9292/v1')
+
+ url = api_base.url_for(self.request, 'image', admin=False)
+ self.assertEqual(url, 'http://public.glance.example.com:9292/v1')
+
+ url = api_base.url_for(self.request, 'image', admin=True)
+ self.assertEqual(url, 'http://admin.glance.example.com:9292/v1')
+
+ url = api_base.url_for(self.request, 'compute')
+ self.assertEqual(url, 'http://public.nova.example.com:8774/v2')
+
+ url = api_base.url_for(self.request, 'compute', admin=False)
+ self.assertEqual(url, 'http://public.nova.example.com:8774/v2')
+
+ url = api_base.url_for(self.request, 'compute', admin=True)
+ self.assertEqual(url, 'http://admin.nova.example.com:8774/v2')
+
+ url = api_base.url_for(self.request, 'volume')
+ self.assertEqual(url, 'http://public.nova.example.com:8776/v1')
+
+ url = api_base.url_for(self.request, 'volume',
+ endpoint_type="internalURL")
+ self.assertEqual(url, 'http://int.nova.example.com:8776/v1')
+
+ url = api_base.url_for(self.request, 'volume', admin=False)
+ self.assertEqual(url, 'http://public.nova.example.com:8776/v1')
+
+ url = api_base.url_for(self.request, 'volume', admin=True)
+ self.assertEqual(url, 'http://admin.nova.example.com:8776/v1')
+
+ self.assertNotIn('notAnApi', self.request.user.service_catalog,
+ 'Select a new nonexistent service catalog key')
+ with self.assertRaises(exceptions.ServiceCatalogException):
+ url = api_base.url_for(self.request, 'notAnApi')
diff --git a/openstack_dashboard/test/api_tests/glance_tests.py b/openstack_dashboard/test/api_tests/glance_tests.py
new file mode 100644
index 000000000..f5b8a0bdb
--- /dev/null
+++ b/openstack_dashboard/test/api_tests/glance_tests.py
@@ -0,0 +1,67 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+class GlanceApiTests(test.APITestCase):
+ def test_snapshot_list_detailed(self):
+ images = self.images.list()
+ filters = {'property-image_type': 'snapshot'}
+ limit = getattr(settings, 'API_RESULT_LIMIT', 1000)
+ page_size = getattr(settings, 'API_RESULT_PAGE_SIZE', 20)
+
+ glanceclient = self.stub_glanceclient()
+ glanceclient.images = self.mox.CreateMockAnything()
+ glanceclient.images.list(page_size=page_size,
+ limit=limit,
+ filters=filters,).AndReturn(images)
+ self.mox.ReplayAll()
+
+ # No assertions are necessary. Verification is handled by mox.
+ api.glance.snapshot_list_detailed(self.request)
+
+ def test_snapshot_list_detailed_pagination(self):
+ images = self.images.list()
+ filters = {'property-image_type': 'snapshot'}
+ page_size = 2
+ temp_page_size = getattr(settings, 'API_RESULT_PAGE_SIZE', None)
+ settings.API_RESULT_PAGE_SIZE = page_size
+ limit = getattr(settings, 'API_RESULT_LIMIT', 1000)
+
+ glanceclient = self.stub_glanceclient()
+ glanceclient.images = self.mox.CreateMockAnything()
+ glanceclient.images.list(limit=limit,
+ page_size=page_size,
+ filters=filters,) \
+ .AndReturn(images[0:page_size])
+ self.mox.ReplayAll()
+
+ # No assertions are necessary. Verification is handled by mox.
+ api.glance.snapshot_list_detailed(self.request)
+
+ # Restore
+ if temp_page_size:
+ settings.API_RESULT_PAGE_SIZE = temp_page_size
+ else:
+ del settings.API_RESULT_PAGE_SIZE
diff --git a/openstack_dashboard/test/api_tests/keystone_tests.py b/openstack_dashboard/test/api_tests/keystone_tests.py
new file mode 100644
index 000000000..e64827890
--- /dev/null
+++ b/openstack_dashboard/test/api_tests/keystone_tests.py
@@ -0,0 +1,98 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 keystoneclient.v2_0 import client as keystone_client
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+class FakeConnection(object):
+ pass
+
+
+class ClientConnectionTests(test.TestCase):
+ def setUp(self):
+ super(ClientConnectionTests, self).setUp()
+ self.mox.StubOutWithMock(keystone_client, "Client")
+ self.internal_url = api.base.url_for(self.request,
+ 'identity',
+ endpoint_type='internalURL')
+ self.admin_url = api.base.url_for(self.request,
+ 'identity',
+ endpoint_type='adminURL')
+ self.conn = FakeConnection()
+
+
+class RoleAPITests(test.APITestCase):
+ def setUp(self):
+ super(RoleAPITests, self).setUp()
+ self.role = self.roles.member
+ self.roles = self.roles.list()
+
+ def test_remove_tenant_user(self):
+ """
+ Tests api.keystone.remove_tenant_user
+
+ Verifies that remove_tenant_user is called with the right arguments
+ after iterating the user's roles.
+
+ There are no assertions in this test because the checking is handled
+ by mox in the VerifyAll() call in tearDown().
+ """
+ keystoneclient = self.stub_keystoneclient()
+ tenant = self.tenants.first()
+
+ keystoneclient.roles = self.mox.CreateMockAnything()
+ keystoneclient.roles.roles_for_user(self.user.id,
+ tenant.id).AndReturn(self.roles)
+ for role in self.roles:
+ keystoneclient.roles.remove_user_role(self.user.id,
+ role.id,
+ tenant.id)
+ self.mox.ReplayAll()
+ api.keystone.remove_tenant_user(self.request, tenant.id, self.user.id)
+
+ def test_get_default_role(self):
+ keystoneclient = self.stub_keystoneclient()
+ keystoneclient.roles = self.mox.CreateMockAnything()
+ keystoneclient.roles.list().AndReturn(self.roles)
+ self.mox.ReplayAll()
+ role = api.keystone.get_default_role(self.request)
+ self.assertEqual(role, self.role)
+ # Verify that a second call doesn't hit the API again,
+ # (it would show up in mox as an unexpected method call)
+ role = api.keystone.get_default_role(self.request)
+
+
+class ServiceAPITests(test.APITestCase):
+ def test_service_wrapper(self):
+ catalog = self.service_catalog
+ identity_data = api.base.get_service_from_catalog(catalog, "identity")
+ identity_data['id'] = 1
+ service = api.keystone.Service(identity_data)
+ self.assertEqual(unicode(service), u"identity (native backend)")
+ self.assertEqual(service.region,
+ identity_data["endpoints"][0]["region"])
+ self.assertEqual(service.url,
+ "http://int.keystone.example.com:5000/v2.0")
+ self.assertEqual(service.host, "int.keystone.example.com")
diff --git a/openstack_dashboard/test/api_tests/nova_tests.py b/openstack_dashboard/test/api_tests/nova_tests.py
new file mode 100644
index 000000000..d3f3ed476
--- /dev/null
+++ b/openstack_dashboard/test/api_tests/nova_tests.py
@@ -0,0 +1,206 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+# Copyright (c) 2012 X.commerce, a business unit of eBay Inc.
+#
+# 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 django import http
+from mox import IsA
+from novaclient.v1_1 import servers
+
+from openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+class ServerWrapperTests(test.TestCase):
+ def test_get_base_attribute(self):
+ server = api.nova.Server(self.servers.first(), self.request)
+ self.assertEqual(server.id, self.servers.first().id)
+
+ def test_image_name(self):
+ image = self.images.first()
+ self.mox.StubOutWithMock(api.glance, 'image_get')
+ api.glance.image_get(IsA(http.HttpRequest),
+ image.id).AndReturn(image)
+ self.mox.ReplayAll()
+
+ server = api.Server(self.servers.first(), self.request)
+ self.assertEqual(server.image_name, image.name)
+
+
+class ComputeApiTests(test.APITestCase):
+ def test_server_reboot(self):
+ server = self.servers.first()
+ HARDNESS = servers.REBOOT_HARD
+
+ novaclient = self.stub_novaclient()
+ novaclient.servers = self.mox.CreateMockAnything()
+ novaclient.servers.get(server.id).AndReturn(server)
+ novaclient.servers.reboot(server.id, HARDNESS)
+ self.mox.ReplayAll()
+
+ ret_val = api.nova.server_reboot(self.request, server.id)
+ self.assertIsNone(ret_val)
+
+ def test_server_vnc_console(self):
+ server = self.servers.first()
+ console = self.servers.console_data
+ console_type = console["console"]["type"]
+
+ novaclient = self.stub_novaclient()
+ novaclient.servers = self.mox.CreateMockAnything()
+ novaclient.servers.get_vnc_console(server.id,
+ console_type).AndReturn(console)
+ self.mox.ReplayAll()
+
+ ret_val = api.server_vnc_console(self.request,
+ server.id,
+ console_type)
+ self.assertIsInstance(ret_val, api.nova.VNCConsole)
+
+ def test_server_list(self):
+ servers = self.servers.list()
+
+ novaclient = self.stub_novaclient()
+ novaclient.servers = self.mox.CreateMockAnything()
+ novaclient.servers.list(True, {'all_tenants': True}).AndReturn(servers)
+ self.mox.ReplayAll()
+
+ ret_val = api.nova.server_list(self.request, all_tenants=True)
+ for server in ret_val:
+ self.assertIsInstance(server, api.Server)
+
+ def test_usage_get(self):
+ novaclient = self.stub_novaclient()
+ novaclient.usage = self.mox.CreateMockAnything()
+ novaclient.usage.get(self.tenant.id,
+ 'start',
+ 'end').AndReturn(self.usages.first())
+ self.mox.ReplayAll()
+
+ ret_val = api.usage_get(self.request, self.tenant.id, 'start', 'end')
+ self.assertIsInstance(ret_val, api.nova.Usage)
+
+ def test_usage_list(self):
+ usages = self.usages.list()
+
+ novaclient = self.stub_novaclient()
+ novaclient.usage = self.mox.CreateMockAnything()
+ novaclient.usage.list('start', 'end', True).AndReturn(usages)
+ self.mox.ReplayAll()
+
+ ret_val = api.usage_list(self.request, 'start', 'end')
+ for usage in ret_val:
+ self.assertIsInstance(usage, api.Usage)
+
+ def test_server_get(self):
+ server = self.servers.first()
+
+ novaclient = self.stub_novaclient()
+ novaclient.servers = self.mox.CreateMockAnything()
+ novaclient.servers.get(server.id).AndReturn(server)
+ self.mox.ReplayAll()
+
+ ret_val = api.server_get(self.request, server.id)
+ self.assertIsInstance(ret_val, api.nova.Server)
+
+ def test_server_remove_floating_ip(self):
+ server = api.nova.Server(self.servers.first(), self.request)
+ floating_ip = self.floating_ips.first()
+
+ novaclient = self.stub_novaclient()
+ novaclient.servers = self.mox.CreateMockAnything()
+ novaclient.floating_ips = self.mox.CreateMockAnything()
+ novaclient.servers.get(server.id).AndReturn(server)
+ novaclient.floating_ips.get(floating_ip.id).AndReturn(floating_ip)
+ novaclient.servers.remove_floating_ip(server.id, floating_ip.ip) \
+ .AndReturn(server)
+ self.mox.ReplayAll()
+
+ server = api.server_remove_floating_ip(self.request,
+ server.id,
+ floating_ip.id)
+ self.assertIsInstance(server, api.nova.Server)
+
+ def test_server_add_floating_ip(self):
+ server = api.nova.Server(self.servers.first(), self.request)
+ floating_ip = self.floating_ips.first()
+ novaclient = self.stub_novaclient()
+
+ novaclient.floating_ips = self.mox.CreateMockAnything()
+ novaclient.servers = self.mox.CreateMockAnything()
+ novaclient.servers.get(server.id).AndReturn(server)
+ novaclient.floating_ips.get(floating_ip.id).AndReturn(floating_ip)
+ novaclient.servers.add_floating_ip(server.id, floating_ip.ip) \
+ .AndReturn(server)
+ self.mox.ReplayAll()
+
+ server = api.server_add_floating_ip(self.request,
+ server.id,
+ floating_ip.id)
+ self.assertIsInstance(server, api.nova.Server)
+
+ @test.create_stubs({api.nova: ('volume_list',
+ 'server_list',
+ 'flavor_list',
+ 'tenant_floating_ip_list',
+ 'tenant_quota_get',)})
+ def test_tenant_quota_usages(self):
+ api.nova.flavor_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.flavors.list())
+ api.nova.tenant_quota_get(IsA(http.HttpRequest), '1') \
+ .AndReturn(self.quotas.first())
+ api.nova.tenant_floating_ip_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.floating_ips.list())
+ api.nova.server_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.servers.list())
+ api.nova.volume_list(IsA(http.HttpRequest)) \
+ .AndReturn(self.volumes.list())
+
+ self.mox.ReplayAll()
+
+ quota_usages = api.tenant_quota_usages(self.request)
+ expected_output = {'gigabytes': {
+ 'used': 80,
+ 'flavor_fields': [],
+ 'quota': 1000},
+ 'ram': {
+ 'available': 8976,
+ 'used': 1024,
+ 'flavor_fields': ['ram'],
+ 'quota': 10000},
+ 'floating_ips': {
+ 'used': 2,
+ 'flavor_fields': [],
+ 'quota': 1},
+ 'instances': {
+ 'used': 2,
+ 'flavor_fields': [],
+ 'quota': 10},
+ 'volumes': {
+ 'used': 3,
+ 'flavor_fields': [],
+ 'quota': 1},
+ 'cores': {
+ 'used': 2,
+ 'flavor_fields': ['vcpus'],
+ 'quota': 10}}
+
+ self.assertEquals(quota_usages, expected_output)
diff --git a/openstack_dashboard/test/api_tests/quantum_tests.py b/openstack_dashboard/test/api_tests/quantum_tests.py
new file mode 100644
index 000000000..22bf459c8
--- /dev/null
+++ b/openstack_dashboard/test/api_tests/quantum_tests.py
@@ -0,0 +1,205 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 NEC Corporation
+#
+# 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 openstack_dashboard import api
+from openstack_dashboard.test import helpers as test
+
+
+class QuantumApiTests(test.APITestCase):
+ def test_network_list(self):
+ networks = {'networks': self.api_networks.list()}
+ subnets = {'subnets': self.api_subnets.list()}
+
+ quantumclient = self.stub_quantumclient()
+ quantumclient.list_networks().AndReturn(networks)
+ quantumclient.list_subnets().AndReturn(subnets)
+ self.mox.ReplayAll()
+
+ ret_val = api.quantum.network_list(self.request)
+ for n in ret_val:
+ self.assertIsInstance(n, api.quantum.Network)
+
+ def test_network_get(self):
+ network = {'network': self.api_networks.first()}
+ subnet = {'subnet': self.api_subnets.first()}
+ network_id = self.api_networks.first()['id']
+ subnet_id = self.api_networks.first()['subnets'][0]
+
+ quantumclient = self.stub_quantumclient()
+ quantumclient.show_network(network_id).AndReturn(network)
+ quantumclient.show_subnet(subnet_id).AndReturn(subnet)
+ self.mox.ReplayAll()
+
+ ret_val = api.quantum.network_get(self.request, network_id)
+ self.assertIsInstance(ret_val, api.quantum.Network)
+
+ def test_network_create(self):
+ network = {'network': self.api_networks.first()}
+
+ quantumclient = self.stub_quantumclient()
+ form_data = {'network': {'name': 'net1'}}
+ quantumclient.create_network(body=form_data).AndReturn(network)
+ self.mox.ReplayAll()
+
+ ret_val = api.quantum.network_create(self.request, name='net1')
+ self.assertIsInstance(ret_val, api.quantum.Network)
+
+ def test_network_modify(self):
+ network = {'network': self.api_networks.first()}
+ network_id = self.api_networks.first()['id']
+
+ quantumclient = self.stub_quantumclient()
+ form_data = {'network': {'name': 'net1'}}
+ quantumclient.update_network(network_id, body=form_data)\
+ .AndReturn(network)
+ self.mox.ReplayAll()
+
+ ret_val = api.quantum.network_modify(self.request, network_id,
+ name='net1')
+ self.assertIsInstance(ret_val, api.quantum.Network)
+
+ def test_network_delete(self):
+ network_id = self.api_networks.first()['id']
+
+ quantumclient = self.stub_quantumclient()
+ quantumclient.delete_network(network_id)
+ self.mox.ReplayAll()
+
+ api.quantum.network_delete(self.request, network_id)
+
+ def test_subnet_list(self):
+ subnets = {'subnets': self.api_subnets.list()}
+
+ quantumclient = self.stub_quantumclient()
+ quantumclient.list_subnets().AndReturn(subnets)
+ self.mox.ReplayAll()
+
+ ret_val = api.quantum.subnet_list(self.request)
+ for n in ret_val:
+ self.assertIsInstance(n, api.quantum.Subnet)
+
+ def test_subnet_get(self):
+ subnet = {'subnet': self.api_subnets.first()}
+ subnet_id = self.api_subnets.first()['id']
+
+ quantumclient = self.stub_quantumclient()
+ quantumclient.show_subnet(subnet_id).AndReturn(subnet)
+ self.mox.ReplayAll()
+
+ ret_val = api.quantum.subnet_get(self.request, subnet_id)
+ self.assertIsInstance(ret_val, api.quantum.Subnet)
+
+ def test_subnet_create(self):
+ subnet_data = self.api_subnets.first()
+ params = {'network_id': subnet_data['network_id'],
+ 'tenant_id': subnet_data['tenant_id'],
+ 'name': subnet_data['name'],
+ 'cidr': subnet_data['cidr'],
+ 'ip_version': subnet_data['ip_version'],
+ 'gateway_ip': subnet_data['gateway_ip']}
+
+ quantumclient = self.stub_quantumclient()
+ quantumclient.create_subnet(body={'subnet': params})\
+ .AndReturn({'subnet': subnet_data})
+ self.mox.ReplayAll()
+
+ ret_val = api.quantum.subnet_create(self.request, **params)
+ self.assertIsInstance(ret_val, api.quantum.Subnet)
+
+ def test_subnet_modify(self):
+ subnet_data = self.api_subnets.first()
+ subnet_id = subnet_data['id']
+ params = {'name': subnet_data['name'],
+ 'gateway_ip': subnet_data['gateway_ip']}
+
+ quantumclient = self.stub_quantumclient()
+ quantumclient.update_subnet(subnet_id, body={'subnet': params})\
+ .AndReturn({'subnet': subnet_data})
+ self.mox.ReplayAll()
+
+ ret_val = api.quantum.subnet_modify(self.request, subnet_id, **params)
+ self.assertIsInstance(ret_val, api.quantum.Subnet)
+
+ def test_subnet_delete(self):
+ subnet_id = self.api_subnets.first()['id']
+
+ quantumclient = self.stub_quantumclient()
+ quantumclient.delete_subnet(subnet_id)
+ self.mox.ReplayAll()
+
+ api.quantum.subnet_delete(self.request, subnet_id)
+
+ def test_port_list(self):
+ ports = {'ports': self.api_ports.list()}
+
+ quantumclient = self.stub_quantumclient()
+ quantumclient.list_ports().AndReturn(ports)
+ self.mox.ReplayAll()
+
+ ret_val = api.quantum.port_list(self.request)
+ for p in ret_val:
+ self.assertIsInstance(p, api.quantum.Port)
+
+ def test_port_get(self):
+ port = {'port': self.api_ports.first()}
+ port_id = self.api_ports.first()['id']
+
+ quantumclient = self.stub_quantumclient()
+ quantumclient.show_port(port_id).AndReturn(port)
+ self.mox.ReplayAll()
+
+ ret_val = api.quantum.port_get(self.request, port_id)
+ self.assertIsInstance(ret_val, api.quantum.Port)
+
+ def test_port_create(self):
+ port_data = self.api_ports.first()
+ params = {'network_id': port_data['network_id'],
+ 'tenant_id': port_data['tenant_id'],
+ 'name': port_data['name'],
+ 'device_id': port_data['device_id']}
+
+ quantumclient = self.stub_quantumclient()
+ quantumclient.create_port(body={'port': params})\
+ .AndReturn({'port': port_data})
+ self.mox.ReplayAll()
+
+ ret_val = api.quantum.port_create(self.request, **params)
+ self.assertIsInstance(ret_val, api.quantum.Port)
+ self.assertEqual(ret_val.id, api.quantum.Port(port_data).id)
+
+ def test_port_modify(self):
+ port_data = self.api_ports.first()
+ port_id = port_data['id']
+ params = {'name': port_data['name'],
+ 'device_id': port_data['device_id']}
+
+ quantumclient = self.stub_quantumclient()
+ quantumclient.update_port(port_id, body={'port': params})\
+ .AndReturn({'port': port_data})
+ self.mox.ReplayAll()
+
+ ret_val = api.quantum.port_modify(self.request, port_id, **params)
+ self.assertIsInstance(ret_val, api.quantum.Port)
+ self.assertEqual(ret_val.id, api.quantum.Port(port_data).id)
+
+ def test_port_delete(self):
+ port_id = self.api_ports.first()['id']
+
+ quantumclient = self.stub_quantumclient()
+ quantumclient.delete_port(port_id)
+ self.mox.ReplayAll()
+
+ api.quantum.port_delete(self.request, port_id)
diff --git a/openstack_dashboard/test/api_tests/swift_tests.py b/openstack_dashboard/test/api_tests/swift_tests.py
new file mode 100644
index 000000000..071eced90
--- /dev/null
+++ b/openstack_dashboard/test/api_tests/swift_tests.py
@@ -0,0 +1,120 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 mox import IsA
+
+from openstack_dashboard import api
+from horizon import exceptions
+from openstack_dashboard.test import helpers as test
+
+
+class SwiftApiTests(test.APITestCase):
+ def test_swift_get_containers(self):
+ containers = self.containers.list()
+ cont_data = [c._apidict for c in containers]
+ swift_api = self.stub_swiftclient()
+ swift_api.get_account(limit=1001,
+ marker=None,
+ full_listing=True).AndReturn([{}, cont_data])
+ self.mox.ReplayAll()
+
+ (conts, more) = api.swift_get_containers(self.request)
+ self.assertEqual(len(conts), len(containers))
+ self.assertFalse(more)
+
+ def test_swift_create_duplicate_container(self):
+ container = self.containers.first()
+ swift_api = self.stub_swiftclient(expected_calls=2)
+ # Check for existence, then create
+ exc = self.exceptions.swift
+ swift_api.head_container(container.name).AndRaise(exc)
+ swift_api.put_container(container.name).AndReturn(container)
+ self.mox.ReplayAll()
+ # Verification handled by mox, no assertions needed.
+ api.swift_create_container(self.request, container.name)
+
+ def test_swift_create_container(self):
+ container = self.containers.first()
+ swift_api = self.stub_swiftclient()
+ swift_api.head_container(container.name).AndReturn(container)
+ self.mox.ReplayAll()
+ # Verification handled by mox, no assertions needed.
+ with self.assertRaises(exceptions.AlreadyExists):
+ api.swift_create_container(self.request, container.name)
+
+ def test_swift_get_objects(self):
+ container = self.containers.first()
+ objects = self.objects.list()
+
+ swift_api = self.stub_swiftclient()
+ swift_api.get_container(container.name,
+ limit=1001,
+ marker=None,
+ prefix=None,
+ delimiter='/',
+ full_listing=True).AndReturn([{}, objects])
+ self.mox.ReplayAll()
+
+ (objs, more) = api.swift_get_objects(self.request, container.name)
+ self.assertEqual(len(objs), len(objects))
+ self.assertFalse(more)
+
+ def test_swift_upload_object(self):
+ container = self.containers.first()
+ obj = self.objects.first()
+ fake_name = 'fake_object.jpg'
+
+ class FakeFile(object):
+ def __init__(self):
+ self.name = fake_name
+ self.data = obj.data
+ self.size = len(obj.data)
+
+ headers = {'X-Object-Meta-Orig-Filename': fake_name}
+
+ swift_api = self.stub_swiftclient()
+ swift_api.put_object(container.name,
+ obj.name,
+ IsA(FakeFile),
+ headers=headers)
+ self.mox.ReplayAll()
+
+ api.swift_upload_object(self.request,
+ container.name,
+ obj.name,
+ FakeFile())
+
+ def test_swift_object_exists(self):
+ container = self.containers.first()
+ obj = self.objects.first()
+
+ swift_api = self.stub_swiftclient(expected_calls=2)
+ swift_api.head_object(container.name, obj.name).AndReturn(container)
+
+ exc = self.exceptions.swift
+ swift_api.head_object(container.name, obj.name).AndRaise(exc)
+ self.mox.ReplayAll()
+
+ args = self.request, container.name, obj.name
+ self.assertTrue(api.swift_object_exists(*args))
+ # Again, for a "non-existent" object
+ self.assertFalse(api.swift_object_exists(*args))
diff --git a/openstack_dashboard/test/helpers.py b/openstack_dashboard/test/helpers.py
new file mode 100644
index 000000000..4180945af
--- /dev/null
+++ b/openstack_dashboard/test/helpers.py
@@ -0,0 +1,298 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 United States Government as represented by the
+# Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+#
+# Copyright 2012 Nebula, Inc.
+#
+# 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 functools import wraps
+import os
+
+from django import http
+from django.conf import settings
+from django.contrib.messages.storage import default_storage
+from django.contrib.auth.middleware import AuthenticationMiddleware
+from django.core.handlers import wsgi
+from django.test.client import RequestFactory
+from django.utils import unittest
+
+import glanceclient
+from keystoneclient.v2_0 import client as keystone_client
+from novaclient.v1_1 import client as nova_client
+from quantumclient.v2_0 import client as quantum_client
+from swiftclient import client as swift_client
+
+import httplib2
+import mox
+
+from openstack_auth import utils, user
+
+from horizon.test import helpers as horizon_helpers
+from horizon import middleware
+
+from openstack_dashboard import api
+from openstack_dashboard import context_processors
+from openstack_dashboard.test.test_data.utils import load_test_data
+
+
+# Makes output of failing mox tests much easier to read.
+wsgi.WSGIRequest.__repr__ = lambda self: "<class 'django.http.HttpRequest'>"
+
+
+def create_stubs(stubs_to_create={}):
+ if not isinstance(stubs_to_create, dict):
+ raise TypeError("create_stub must be passed a dict, but a %s was "
+ "given." % type(stubs_to_create).__name__)
+
+ def inner_stub_out(fn):
+ @wraps(fn)
+ def instance_stub_out(self):
+ for key in stubs_to_create:
+ if not (isinstance(stubs_to_create[key], tuple) or
+ isinstance(stubs_to_create[key], list)):
+ raise TypeError("The values of the create_stub "
+ "dict must be lists or tuples, but "
+ "is a %s."
+ % type(stubs_to_create[key]).__name__)
+
+ for value in stubs_to_create[key]:
+ self.mox.StubOutWithMock(key, value)
+ return fn(self)
+ return instance_stub_out
+ return inner_stub_out
+
+
+class RequestFactoryWithMessages(RequestFactory):
+ def get(self, *args, **kwargs):
+ req = super(RequestFactoryWithMessages, self).get(*args, **kwargs)
+ req.user = utils.get_user(req)
+ req.session = []
+ req._messages = default_storage(req)
+ return req
+
+ def post(self, *args, **kwargs):
+ req = super(RequestFactoryWithMessages, self).post(*args, **kwargs)
+ req.user = utils.get_user(req)
+ req.session = []
+ req._messages = default_storage(req)
+ return req
+
+
+@unittest.skipIf(os.environ.get('SKIP_UNITTESTS', False),
+ "The SKIP_UNITTESTS env variable is set.")
+class TestCase(horizon_helpers.TestCase):
+ """
+ Specialized base test case class for Horizon which gives access to
+ numerous additional features:
+
+ * A full suite of test data through various attached objects and
+ managers (e.g. ``self.servers``, ``self.user``, etc.). See the
+ docs for :class:`~horizon.tests.test_data.utils.TestData` for more
+ information.
+ * The ``mox`` mocking framework via ``self.mox``.
+ * A set of request context data via ``self.context``.
+ * A ``RequestFactory`` class which supports Django's ``contrib.messages``
+ framework via ``self.factory``.
+ * A ready-to-go request object via ``self.request``.
+ * The ability to override specific time data controls for easier testing.
+ * Several handy additional assertion methods.
+ """
+ def setUp(self):
+ load_test_data(self)
+ self.mox = mox.Mox()
+ self.factory = RequestFactoryWithMessages()
+ self.context = {'authorized_tenants': self.tenants.list()}
+
+ def fake_conn_request(*args, **kwargs):
+ raise Exception("An external URI request tried to escape through "
+ "an httplib2 client. Args: %s, kwargs: %s"
+ % (args, kwargs))
+
+ self._real_conn_request = httplib2.Http._conn_request
+ httplib2.Http._conn_request = fake_conn_request
+
+ self._real_context_processor = context_processors.openstack
+ context_processors.openstack = lambda request: self.context
+
+ self._real_get_user = utils.get_user
+ tenants = self.context['authorized_tenants']
+ self.setActiveUser(id=self.user.id,
+ token=self.token,
+ username=self.user.name,
+ tenant_id=self.tenant.id,
+ service_catalog=self.service_catalog,
+ authorized_tenants=tenants)
+ self.request = http.HttpRequest()
+ self.request.session = self.client._session()
+ self.request.session['token'] = self.token.id
+ middleware.HorizonMiddleware().process_request(self.request)
+ AuthenticationMiddleware().process_request(self.request)
+ os.environ["HORIZON_TEST_RUN"] = "True"
+
+ def tearDown(self):
+ self.mox.UnsetStubs()
+ httplib2.Http._conn_request = self._real_conn_request
+ context_processors.openstack = self._real_context_processor
+ utils.get_user = self._real_get_user
+ self.mox.VerifyAll()
+ del os.environ["HORIZON_TEST_RUN"]
+
+ def setActiveUser(self, id=None, token=None, username=None, tenant_id=None,
+ service_catalog=None, tenant_name=None, roles=None,
+ authorized_tenants=None, enabled=True):
+ def get_user(request):
+ return user.User(id=id,
+ token=token,
+ user=username,
+ tenant_id=tenant_id,
+ service_catalog=service_catalog,
+ roles=roles,
+ enabled=enabled,
+ authorized_tenants=authorized_tenants,
+ endpoint=settings.OPENSTACK_KEYSTONE_URL)
+ utils.get_user = get_user
+
+ def assertRedirectsNoFollow(self, response, expected_url):
+ """
+ Asserts that the given response issued a 302 redirect without
+ processing the view which is redirected to.
+ """
+ assert (response.status_code / 100 == 3), \
+ "The response did not return a redirect."
+ self.assertEqual(response._headers.get('location', None),
+ ('Location', settings.TESTSERVER + expected_url))
+ self.assertEqual(response.status_code, 302)
+
+ def assertNoFormErrors(self, response, context_name="form"):
+ """
+ Asserts that the response either does not contain a form in it's
+ context, or that if it does, that form has no errors.
+ """
+ context = getattr(response, "context", {})
+ if not context or context_name not in context:
+ return True
+ errors = response.context[context_name]._errors
+ assert len(errors) == 0, \
+ "Unexpected errors were found on the form: %s" % errors
+
+ def assertFormErrors(self, response, count=0, message=None,
+ context_name="form"):
+ """
+ Asserts that the response does contain a form in it's
+ context, and that form has errors, if count were given,
+ it must match the exact numbers of errors
+ """
+ context = getattr(response, "context", {})
+ assert (context and context_name in context), \
+ "The response did not contain a form."
+ errors = response.context[context_name]._errors
+ if count:
+ assert len(errors) == count, \
+ "%d errors were found on the form, %d expected" % \
+ (len(errors), count)
+ if message and message not in unicode(errors):
+ self.fail("Expected message not found, instead found: %s"
+ % ["%s: %s" % (key, [e for e in field_errors]) for
+ (key, field_errors) in errors.items()])
+ else:
+ assert len(errors) > 0, "No errors were found on the form"
+
+
+class BaseAdminViewTests(TestCase):
+ """
+ A ``TestCase`` subclass which sets an active user with the "admin" role
+ for testing admin-only views and functionality.
+ """
+ def setActiveUser(self, *args, **kwargs):
+ if "roles" not in kwargs:
+ kwargs['roles'] = [self.roles.admin._info]
+ super(BaseAdminViewTests, self).setActiveUser(*args, **kwargs)
+
+
+class APITestCase(TestCase):
+ """
+ The ``APITestCase`` class is for use with tests which deal with the
+ underlying clients rather than stubbing out the
+ openstack_dashboard.api.* methods.
+ """
+ def setUp(self):
+ super(APITestCase, self).setUp()
+
+ def fake_keystoneclient(request, admin=False):
+ """
+ Wrapper function which returns the stub keystoneclient. Only
+ necessary because the function takes too many arguments to
+ conveniently be a lambda.
+ """
+ return self.stub_keystoneclient()
+
+ # Store the original clients
+ self._original_glanceclient = api.glance.glanceclient
+ self._original_keystoneclient = api.keystone.keystoneclient
+ self._original_novaclient = api.nova.novaclient
+ self._original_quantumclient = api.quantum.quantumclient
+
+ # Replace the clients with our stubs.
+ api.glance.glanceclient = lambda request: self.stub_glanceclient()
+ api.keystone.keystoneclient = fake_keystoneclient
+ api.nova.novaclient = lambda request: self.stub_novaclient()
+ api.quantum.quantumclient = lambda request: self.stub_quantumclient()
+
+ def tearDown(self):
+ super(APITestCase, self).tearDown()
+ api.glance.glanceclient = self._original_glanceclient
+ api.nova.novaclient = self._original_novaclient
+ api.keystone.keystoneclient = self._original_keystoneclient
+ api.quantum.quantumclient = self._original_quantumclient
+
+ def stub_novaclient(self):
+ if not hasattr(self, "novaclient"):
+ self.mox.StubOutWithMock(nova_client, 'Client')
+ self.novaclient = self.mox.CreateMock(nova_client.Client)
+ return self.novaclient
+
+ def stub_keystoneclient(self):
+ if not hasattr(self, "keystoneclient"):
+ self.mox.StubOutWithMock(keystone_client, 'Client')
+ self.keystoneclient = self.mox.CreateMock(keystone_client.Client)
+ return self.keystoneclient
+
+ def stub_glanceclient(self):
+ if not hasattr(self, "glanceclient"):
+ self.mox.StubOutWithMock(glanceclient, 'Client')
+ self.glanceclient = self.mox.CreateMock(glanceclient.Client)
+ return self.glanceclient
+
+ def stub_quantumclient(self):
+ if not hasattr(self, "quantumclient"):
+ self.mox.StubOutWithMock(quantum_client, 'Client')
+ self.quantumclient = self.mox.CreateMock(quantum_client.Client)
+ return self.quantumclient
+
+ def stub_swiftclient(self, expected_calls=1):
+ if not hasattr(self, "swiftclient"):
+ self.mox.StubOutWithMock(swift_client, 'Connection')
+ self.swiftclient = self.mox.CreateMock(swift_client.Connection)
+ while expected_calls:
+ swift_client.Connection(None,
+ mox.IgnoreArg(),
+ None,
+ preauthtoken=mox.IgnoreArg(),
+ preauthurl=mox.IgnoreArg(),
+ auth_version="2.0") \
+ .AndReturn(self.swiftclient)
+ expected_calls -= 1
+ return self.swiftclient
diff --git a/openstack_dashboard/test/settings.py b/openstack_dashboard/test/settings.py
index d3f376d0c..d03d26888 100644
--- a/openstack_dashboard/test/settings.py
+++ b/openstack_dashboard/test/settings.py
@@ -1,14 +1,85 @@
import os
-from horizon.tests.testsettings import *
+from django.utils.translation import ugettext_lazy as _
+
+from horizon.test.settings import *
from horizon.utils.secret_key import generate_or_read_from_file
+from openstack_dashboard.exceptions import UNAUTHORIZED, RECOVERABLE, NOT_FOUND
+
+
TEST_DIR = os.path.dirname(os.path.abspath(__file__))
ROOT_PATH = os.path.abspath(os.path.join(TEST_DIR, ".."))
SECRET_KEY = generate_or_read_from_file(os.path.join(TEST_DIR,
'.secret_key_store'))
ROOT_URLCONF = 'openstack_dashboard.urls'
-TEMPLATE_DIRS = (os.path.join(ROOT_PATH, 'templates'),)
-STATICFILES_DIRS = (os.path.join(ROOT_PATH, 'static'),)
-INSTALLED_APPS += ('openstack_dashboard',)
+TEMPLATE_DIRS = (
+ os.path.join(TEST_DIR, 'templates'),
+ #os.path.join(ROOT_PATH, 'templates'),
+)
+
+TEMPLATE_CONTEXT_PROCESSORS += (
+ 'openstack_dashboard.context_processors.openstack',
+)
+
+INSTALLED_APPS = (
+ 'django.contrib.sessions',
+ 'django.contrib.staticfiles',
+ 'django.contrib.messages',
+ 'django.contrib.humanize',
+ 'django_nose',
+ 'openstack_auth',
+ 'compressor',
+ 'horizon',
+ 'openstack_dashboard',
+ 'openstack_dashboard.dashboards.project',
+ 'openstack_dashboard.dashboards.admin',
+ 'openstack_dashboard.dashboards.settings',
+)
+
+AUTHENTICATION_BACKENDS = ('openstack_auth.backend.KeystoneBackend',)
+
+SITE_BRANDING = 'OpenStack'
+
+HORIZON_CONFIG = {
+ 'dashboards': ('project', 'admin', 'settings'),
+ 'default_dashboard': 'project',
+ "password_validator": {
+ "regex": '^.{8,18}$',
+ "help_text": _("Password must be between 8 and 18 characters.")
+ },
+ 'user_home': None,
+ 'help_url': "http://docs.openstack.org",
+ 'exceptions': {'recoverable': RECOVERABLE,
+ 'not_found': NOT_FOUND,
+ 'unauthorized': UNAUTHORIZED},
+}
+
+AVAILABLE_REGIONS = [
+ ('http://localhost:5000/v2.0', 'local'),
+ ('http://remote:5000/v2.0', 'remote'),
+]
+
+OPENSTACK_KEYSTONE_URL = "http://localhost:5000/v2.0"
+OPENSTACK_KEYSTONE_DEFAULT_ROLE = "Member"
+
+OPENSTACK_KEYSTONE_BACKEND = {
+ 'name': 'native',
+ 'can_edit_user': True
+}
+
+OPENSTACK_HYPERVISOR_FEATURES = {
+ 'can_set_mount_point': True
+}
+
+LOGGING['loggers']['openstack_dashboard'] = {
+ 'handlers': ['test'],
+ 'propagate': False,
+}
+
+NOSE_ARGS = ['--nocapture',
+ '--nologcapture',
+ '--cover-package=openstack_dashboard',
+ '--cover-inclusive',
+ '--all-modules']
diff --git a/openstack_dashboard/test/templates/404.html b/openstack_dashboard/test/templates/404.html
new file mode 100644
index 000000000..15f0063e8
--- /dev/null
+++ b/openstack_dashboard/test/templates/404.html
@@ -0,0 +1 @@
+404 NOT FOUND
diff --git a/openstack_dashboard/test/templates/500.html b/openstack_dashboard/test/templates/500.html
new file mode 100644
index 000000000..ab146d759
--- /dev/null
+++ b/openstack_dashboard/test/templates/500.html
@@ -0,0 +1 @@
+500 ERROR
diff --git a/openstack_dashboard/test/templates/_tab.html b/openstack_dashboard/test/templates/_tab.html
new file mode 100644
index 000000000..e336d4116
--- /dev/null
+++ b/openstack_dashboard/test/templates/_tab.html
@@ -0,0 +1 @@
+{{ tab.name }}
diff --git a/openstack_dashboard/test/templates/base-sidebar.html b/openstack_dashboard/test/templates/base-sidebar.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/test/templates/base-sidebar.html
diff --git a/openstack_dashboard/test/templates/registration/login.html b/openstack_dashboard/test/templates/registration/login.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/test/templates/registration/login.html
diff --git a/openstack_dashboard/test/templates/tab_group.html b/openstack_dashboard/test/templates/tab_group.html
new file mode 100644
index 000000000..94b2e5179
--- /dev/null
+++ b/openstack_dashboard/test/templates/tab_group.html
@@ -0,0 +1 @@
+{{ tab_group.render }}
diff --git a/openstack_dashboard/test/templates/workflow.html b/openstack_dashboard/test/templates/workflow.html
new file mode 100644
index 000000000..02ec6658a
--- /dev/null
+++ b/openstack_dashboard/test/templates/workflow.html
@@ -0,0 +1 @@
+{{ workflow.render }}
diff --git a/openstack_dashboard/test/test_data/__init__.py b/openstack_dashboard/test/test_data/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/openstack_dashboard/test/test_data/__init__.py
diff --git a/openstack_dashboard/test/test_data/exceptions.py b/openstack_dashboard/test/test_data/exceptions.py
new file mode 100644
index 000000000..9b9583eb5
--- /dev/null
+++ b/openstack_dashboard/test/test_data/exceptions.py
@@ -0,0 +1,67 @@
+# Copyright 2012 Nebula, Inc.
+#
+# 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 glanceclient.exc as glance_exceptions
+from keystoneclient import exceptions as keystone_exceptions
+from novaclient import exceptions as nova_exceptions
+from quantumclient.common import exceptions as quantum_exceptions
+from swiftclient import client as swift_exceptions
+from cinderclient import exceptions as cinder_exceptions
+
+from .utils import TestDataContainer
+
+
+def create_stubbed_exception(cls, status_code=500):
+ msg = "Expected failure."
+
+ def fake_init_exception(self, code, message):
+ self.code = code
+ self.message = message
+
+ def fake_str(self):
+ return str(self.message)
+
+ def fake_unicode(self):
+ return unicode(self.message)
+
+ cls.__init__ = fake_init_exception
+ cls.__str__ = fake_str
+ cls.__unicode__ = fake_unicode
+ cls.silence_logging = True
+ return cls(status_code, msg)
+
+
+def data(TEST):
+ TEST.exceptions = TestDataContainer()
+
+ unauth = keystone_exceptions.Unauthorized
+ TEST.exceptions.keystone_unauthorized = create_stubbed_exception(unauth)
+
+ keystone_exception = keystone_exceptions.ClientException
+ TEST.exceptions.keystone = create_stubbed_exception(keystone_exception)
+
+ nova_exception = nova_exceptions.ClientException
+ TEST.exceptions.nova = create_stubbed_exception(nova_exception)
+
+ glance_exception = glance_exceptions.ClientException
+ TEST.exceptions.glance = create_stubbed_exception(glance_exception)
+
+ quantum_exception = quantum_exceptions.QuantumClientException
+ TEST.exceptions.quantum = create_stubbed_exception(quantum_exception)
+
+ swift_exception = swift_exceptions.ClientException
+ TEST.exceptions.swift = create_stubbed_exception(swift_exception)
+
+ cinder_exception = cinder_exceptions.BadRequest
+ TEST.exceptions.cinder = create_stubbed_exception(cinder_exception)
diff --git a/openstack_dashboard/test/test_data/glance_data.py b/openstack_dashboard/test/test_data/glance_data.py
new file mode 100644
index 000000000..6fa67b82d
--- /dev/null
+++ b/openstack_dashboard/test/test_data/glance_data.py
@@ -0,0 +1,89 @@
+# Copyright 2012 Nebula, Inc.
+#
+# 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 glanceclient.v1.images import Image, ImageManager
+
+from .utils import TestDataContainer
+
+
+def data(TEST):
+ TEST.images = TestDataContainer()
+ TEST.snapshots = TestDataContainer()
+
+ # Snapshots
+ snapshot_dict = {'name': u'snapshot',
+ 'container_format': u'ami',
+ 'id': 3,
+ 'status': "active",
+ 'owner': TEST.tenant.id,
+ 'properties': {'image_type': u'snapshot'}}
+ snapshot_dict_no_owner = {'name': u'snapshot 2',
+ 'container_format': u'ami',
+ 'id': 4,
+ 'status': "active",
+ 'owner': None,
+ 'properties': {'image_type': u'snapshot'}}
+ snapshot_dict_queued = {'name': u'snapshot 2',
+ 'container_format': u'ami',
+ 'id': 5,
+ 'status': "queued",
+ 'owner': TEST.tenant.id,
+ 'properties': {'image_type': u'snapshot'}}
+ snapshot = Image(ImageManager(None), snapshot_dict)
+ TEST.snapshots.add(snapshot)
+ snapshot = Image(ImageManager(None), snapshot_dict_no_owner)
+ TEST.snapshots.add(snapshot)
+ snapshot = Image(ImageManager(None), snapshot_dict_queued)
+ TEST.snapshots.add(snapshot)
+
+ # Images
+ image_dict = {'id': '007e7d55-fe1e-4c5c-bf08-44b4a4964822',
+ 'name': 'public_image',
+ 'status': "active",
+ 'owner': TEST.tenant.id,
+ 'container_format': 'novaImage',
+ 'properties': {'image_type': u'image'}}
+ public_image = Image(ImageManager(None), image_dict)
+
+ image_dict = {'id': 'a001c047-22f8-47d0-80a1-8ec94a9524fe',
+ 'name': 'private_image',
+ 'status': "active",
+ 'owner': TEST.tenant.id,
+ 'container_format': 'aki'}
+ private_image = Image(ImageManager(None), image_dict)
+
+ image_dict = {'id': '278905a6-4b52-4d1e-98f9-8c57bb25ba32',
+ 'name': 'public_image 2',
+ 'status': "active",
+ 'owner': TEST.tenant.id,
+ 'container_format': 'novaImage',
+ 'properties': {'image_type': u'image'}}
+ public_image2 = Image(ImageManager(None), image_dict)
+
+ image_dict = {'id': '710a1acf-a3e3-41dd-a32d-5d6b6c86ea10',
+ 'name': 'private_image 2',
+ 'status': "active",
+ 'owner': TEST.tenant.id,
+ 'container_format': 'aki'}
+ private_image2 = Image(ImageManager(None), image_dict)
+
+ image_dict = {'id': '7cd892fd-5652-40f3-a450-547615680132',
+ 'name': 'private_image 3',
+ 'status': "active",
+ 'owner': TEST.tenant.id,
+ 'container_format': 'aki'}
+ private_image3 = Image(ImageManager(None), image_dict)
+
+ TEST.images.add(public_image, private_image,
+ public_image2, private_image2, private_image3)
diff --git a/openstack_dashboard/test/test_data/keystone_data.py b/openstack_dashboard/test/test_data/keystone_data.py
new file mode 100644
index 000000000..ae48b2149
--- /dev/null
+++ b/openstack_dashboard/test/test_data/keystone_data.py
@@ -0,0 +1,160 @@
+# Copyright 2012 Nebula, Inc.
+#
+# 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 datetime import timedelta
+
+from django.conf import settings
+from django.utils import datetime_safe
+
+from keystoneclient.v2_0 import users, tenants, tokens, roles, ec2
+
+from .utils import TestDataContainer
+
+
+# Dummy service catalog with all service.
+# All endpoint URLs should point to example.com.
+# Try to keep them as accurate to real data as possible (ports, URIs, etc.)
+SERVICE_CATALOG = [
+ {"type": "compute",
+ "name": "nova",
+ "endpoints_links": [],
+ "endpoints": [
+ {"region": "RegionOne",
+ "adminURL": "http://admin.nova.example.com:8774/v2",
+ "internalURL": "http://int.nova.example.com:8774/v2",
+ "publicURL": "http://public.nova.example.com:8774/v2"}]},
+ {"type": "volume",
+ "name": "nova",
+ "endpoints_links": [],
+ "endpoints": [
+ {"region": "RegionOne",
+ "adminURL": "http://admin.nova.example.com:8776/v1",
+ "internalURL": "http://int.nova.example.com:8776/v1",
+ "publicURL": "http://public.nova.example.com:8776/v1"}]},
+ {"type": "image",
+ "name": "glance",
+ "endpoints_links": [],
+ "endpoints": [
+ {"region": "RegionOne",
+ "adminURL": "http://admin.glance.example.com:9292/v1",
+ "internalURL": "http://int.glance.example.com:9292/v1",
+ "publicURL": "http://public.glance.example.com:9292/v1"}]},
+ {"type": "identity",
+ "name": "keystone",
+ "endpoints_links": [],
+ "endpoints": [
+ {"region": "RegionOne",
+ "adminURL": "http://admin.keystone.example.com:35357/v2.0",
+ "internalURL": "http://int.keystone.example.com:5000/v2.0",
+ "publicURL": "http://public.keystone.example.com:5000/v2.0"}]},
+ {"type": "object-store",
+ "name": "swift",
+ "endpoints_links": [],
+ "endpoints": [
+ {"region": "RegionOne",
+ "adminURL": "http://admin.swift.example.com:8080/",
+ "internalURL": "http://int.swift.example.com:8080/",
+ "publicURL": "http://public.swift.example.com:8080/"}]},
+ {"type": "network",
+ "name": "quantum",
+ "endpoints_links": [],
+ "endpoints": [
+ {"region": "RegionOne",
+ "adminURL": "http://admin.quantum.example.com:9696/",
+ "internalURL": "http://int.quantum.example.com:9696/",
+ "publicURL": "http://public.quantum.example.com:9696/"}]},
+ {"type": "ec2",
+ "name": "EC2 Service",
+ "endpoints_links": [],
+ "endpoints": [
+ {"region": "RegionOne",
+ "adminURL": "http://admin.nova.example.com:8773/services/Admin",
+ "publicURL": "http://public.nova.example.com:8773/services/Cloud",
+ "internalURL": "http://int.nova.example.com:8773/services/Cloud"}]}
+]
+
+
+def data(TEST):
+ TEST.service_catalog = SERVICE_CATALOG
+ TEST.tokens = TestDataContainer()
+ TEST.users = TestDataContainer()
+ TEST.tenants = TestDataContainer()
+ TEST.roles = TestDataContainer()
+ TEST.ec2 = TestDataContainer()
+
+ admin_role_dict = {'id': '1',
+ 'name': 'admin'}
+ admin_role = roles.Role(roles.RoleManager, admin_role_dict)
+ member_role_dict = {'id': "2",
+ 'name': settings.OPENSTACK_KEYSTONE_DEFAULT_ROLE}
+ member_role = roles.Role(roles.RoleManager, member_role_dict)
+ TEST.roles.add(member_role, admin_role)
+ TEST.roles.admin = admin_role
+ TEST.roles.member = member_role
+
+ user_dict = {'id': "1",
+ 'name': 'test_user',
+ 'email': 'test@example.com',
+ 'password': 'password',
+ 'token': 'test_token',
+ 'enabled': True}
+ user = users.User(users.UserManager(None), user_dict)
+ user_dict.update({'id': "2",
+ 'name': 'user_two',
+ 'email': 'two@example.com'})
+ user2 = users.User(users.UserManager(None), user_dict)
+ TEST.users.add(user, user2)
+ TEST.user = user # Your "current" user
+ TEST.user.service_catalog = SERVICE_CATALOG
+
+ tenant_dict = {'id': "1",
+ 'name': 'test_tenant',
+ 'description': "a test tenant.",
+ 'enabled': True}
+ tenant_dict_2 = {'id': "2",
+ 'name': 'disabled_tenant',
+ 'description': "a disabled test tenant.",
+ 'enabled': False}
+ tenant = tenants.Tenant(tenants.TenantManager, tenant_dict)
+ disabled_tenant = tenants.Tenant(tenants.TenantManager, tenant_dict_2)
+ TEST.tenants.add(tenant, disabled_tenant)
+ TEST.tenant = tenant # Your "current" tenant
+
+ tomorrow = datetime_safe.datetime.now() + timedelta(days=1)
+ expiration = datetime_safe.datetime.isoformat(tomorrow)
+
+ scoped_token = tokens.Token(tokens.TokenManager,
+ dict(token={"id": "test_token_id",
+ "expires": expiration,
+ "tenant": tenant_dict,
+ "tenants": [tenant_dict]},
+ user={"id": "test_user_id",
+ "name": "test_user",
+ "roles": [member_role_dict]},
+ serviceCatalog=TEST.service_catalog))
+ unscoped_token = tokens.Token(tokens.TokenManager,
+ dict(token={"id": "test_token_id",
+ "expires": expiration},
+ user={"id": "test_user_id",
+ "name": "test_user",
+ "roles": [member_role_dict]},
+ serviceCatalog=TEST.service_catalog))
+ TEST.tokens.add(scoped_token, unscoped_token)
+ TEST.token = scoped_token # your "current" token.
+ TEST.tokens.scoped_token = scoped_token
+ TEST.tokens.unscoped_token = unscoped_token
+
+ access_secret = ec2.EC2(ec2.CredentialsManager, {"access": "access",
+ "secret": "secret"})
+ TEST.ec2.add(access_secret)
diff --git a/openstack_dashboard/test/test_data/nova_data.py b/openstack_dashboard/test/test_data/nova_data.py
new file mode 100644
index 000000000..a2876f5bb
--- /dev/null
+++ b/openstack_dashboard/test/test_data/nova_data.py
@@ -0,0 +1,343 @@
+# Copyright 2012 Nebula, Inc.
+#
+# 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 json
+
+from novaclient.v1_1 import (flavors, keypairs, servers, volumes, quotas,
+ floating_ips, usage, certs,
+ volume_snapshots as vol_snaps,
+ security_group_rules as rules,
+ security_groups as sec_groups)
+
+from .utils import TestDataContainer
+
+
+SERVER_DATA = """
+{
+ "server": {
+ "OS-EXT-SRV-ATTR:instance_name": "instance-00000005",
+ "OS-EXT-SRV-ATTR:host": "instance-host",
+ "OS-EXT-STS:task_state": null,
+ "addresses": {
+ "private": [
+ {
+ "version": 4,
+ "addr": "10.0.0.1"
+ }
+ ]
+ },
+ "links": [
+ {
+ "href": "%(host)s/v1.1/%(tenant_id)s/servers/%(server_id)s",
+ "rel": "self"
+ },
+ {
+ "href": "%(host)s/%(tenant_id)s/servers/%(server_id)s",
+ "rel": "bookmark"
+ }
+ ],
+ "image": {
+ "id": "%(image_id)s",
+ "links": [
+ {
+ "href": "%(host)s/%(tenant_id)s/images/%(image_id)s",
+ "rel": "bookmark"
+ }
+ ]
+ },
+ "OS-EXT-STS:vm_state": "active",
+ "flavor": {
+ "id": "%(flavor_id)s",
+ "links": [
+ {
+ "href": "%(host)s/%(tenant_id)s/flavors/%(flavor_id)s",
+ "rel": "bookmark"
+ }
+ ]
+ },
+ "id": "%(server_id)s",
+ "user_id": "%(user_id)s",
+ "OS-DCF:diskConfig": "MANUAL",
+ "accessIPv4": "",
+ "accessIPv6": "",
+ "progress": null,
+ "OS-EXT-STS:power_state": 1,
+ "config_drive": "",
+ "status": "%(status)s",
+ "updated": "2012-02-28T19:51:27Z",
+ "hostId": "c461ea283faa0ab5d777073c93b126c68139e4e45934d4fc37e403c2",
+ "key_name": "%(key_name)s",
+ "name": "%(name)s",
+ "created": "2012-02-28T19:51:17Z",
+ "tenant_id": "%(tenant_id)s",
+ "metadata": {"someMetaLabel": "someMetaData",
+ "some<b>html</b>label": "<!--",
+ "empty": ""}
+ }
+}
+"""
+
+
+USAGE_DATA = """
+{
+ "total_memory_mb_usage": 64246.89777777778,
+ "total_vcpus_usage": 125.48222222222223,
+ "total_hours": 125.48222222222223,
+ "total_local_gb_usage": 0,
+ "tenant_id": "%(tenant_id)s",
+ "stop": "2012-01-31 23:59:59",
+ "start": "2012-01-01 00:00:00",
+ "server_usages": [
+ {
+ "memory_mb": %(flavor_ram)s,
+ "uptime": 442321,
+ "started_at": "2012-01-26 20:38:21",
+ "ended_at": null,
+ "name": "%(instance_name)s",
+ "tenant_id": "%(tenant_id)s",
+ "state": "active",
+ "hours": 122.87361111111112,
+ "vcpus": %(flavor_vcpus)s,
+ "flavor": "%(flavor_name)s",
+ "local_gb": %(flavor_disk)s
+ },
+ {
+ "memory_mb": %(flavor_ram)s,
+ "uptime": 9367,
+ "started_at": "2012-01-31 20:54:15",
+ "ended_at": null,
+ "name": "%(instance_name)s",
+ "tenant_id": "%(tenant_id)s",
+ "state": "active",
+ "hours": 2.608611111111111,
+ "vcpus": %(flavor_vcpus)s,
+ "flavor": "%(flavor_name)s",
+ "local_gb": %(flavor_disk)s
+ }
+ ]
+}
+"""
+
+
+def data(TEST):
+ TEST.servers = TestDataContainer()
+ TEST.flavors = TestDataContainer()
+ TEST.keypairs = TestDataContainer()
+ TEST.security_groups = TestDataContainer()
+ TEST.security_group_rules = TestDataContainer()
+ TEST.volumes = TestDataContainer()
+ TEST.quotas = TestDataContainer()
+ TEST.quota_usages = TestDataContainer()
+ TEST.floating_ips = TestDataContainer()
+ TEST.usages = TestDataContainer()
+ TEST.certs = TestDataContainer()
+ TEST.volume_snapshots = TestDataContainer()
+
+ # Volumes
+ volume = volumes.Volume(volumes.VolumeManager(None),
+ dict(id="41023e92-8008-4c8b-8059-7f2293ff3775",
+ name='test_volume',
+ status='available',
+ size=40,
+ display_name='Volume name',
+ created_at='2012-04-01 10:30:00',
+ attachments=[]))
+ nameless_volume = volumes.Volume(volumes.VolumeManager(None),
+ dict(id="3b189ac8-9166-ac7f-90c9-16c8bf9e01ac",
+ name='',
+ status='in-use',
+ size=10,
+ display_name='',
+ display_description='',
+ device="/dev/hda",
+ created_at='2010-11-21 18:34:25',
+ attachments=[{"id": "1", "server_id": '1',
+ "device": "/dev/hda"}]))
+ attached_volume = volumes.Volume(volumes.VolumeManager(None),
+ dict(id="8cba67c1-2741-6c79-5ab6-9c2bf8c96ab0",
+ name='my_volume',
+ status='in-use',
+ size=30,
+ display_name='My Volume',
+ display_description='',
+ device="/dev/hdk",
+ created_at='2011-05-01 11:54:33',
+ attachments=[{"id": "2", "server_id": '1',
+ "device": "/dev/hdk"}]))
+ TEST.volumes.add(volume)
+ TEST.volumes.add(nameless_volume)
+ TEST.volumes.add(attached_volume)
+
+ # Flavors
+ flavor_1 = flavors.Flavor(flavors.FlavorManager(None),
+ {'id': "1",
+ 'name': 'm1.tiny',
+ 'vcpus': 1,
+ 'disk': 0,
+ 'ram': 512,
+ 'OS-FLV-EXT-DATA:ephemeral': 0})
+ flavor_2 = flavors.Flavor(flavors.FlavorManager(None),
+ {'id': "2",
+ 'name': 'm1.massive',
+ 'vcpus': 1000,
+ 'disk': 1024,
+ 'ram': 10000,
+ 'OS-FLV-EXT-DATA:ephemeral': 2048})
+ TEST.flavors.add(flavor_1, flavor_2)
+
+ # Keypairs
+ keypair = keypairs.Keypair(keypairs.KeypairManager(None),
+ dict(name='keyName'))
+ TEST.keypairs.add(keypair)
+
+ # Security Groups
+ sg_manager = sec_groups.SecurityGroupManager(None)
+ sec_group_1 = sec_groups.SecurityGroup(sg_manager,
+ {"rules": [],
+ "tenant_id": TEST.tenant.id,
+ "id": 1,
+ "name": u"default",
+ "description": u"default"})
+ sec_group_2 = sec_groups.SecurityGroup(sg_manager,
+ {"rules": [],
+ "tenant_id": TEST.tenant.id,
+ "id": 2,
+ "name": u"other_group",
+ "description": u"Not default."})
+
+ rule = {'id': 1,
+ 'ip_protocol': u"tcp",
+ 'from_port': u"80",
+ 'to_port': u"80",
+ 'parent_group_id': 1,
+ 'ip_range': {'cidr': u"0.0.0.0/32"}}
+
+ icmp_rule = {'id': 2,
+ 'ip_protocol': u"icmp",
+ 'from_port': u"9",
+ 'to_port': u"5",
+ 'parent_group_id': 1,
+ 'ip_range': {'cidr': u"0.0.0.0/32"}}
+
+ group_rule = {'id': 3,
+ 'ip_protocol': u"tcp",
+ 'from_port': u"80",
+ 'to_port': u"80",
+ 'parent_group_id': 1,
+ 'source_group_id': 1}
+
+ rule_obj = rules.SecurityGroupRule(rules.SecurityGroupRuleManager(None),
+ rule)
+ rule_obj2 = rules.SecurityGroupRule(rules.SecurityGroupRuleManager(None),
+ icmp_rule)
+ rule_obj3 = rules.SecurityGroupRule(rules.SecurityGroupRuleManager(None),
+ group_rule)
+
+ TEST.security_group_rules.add(rule_obj)
+ TEST.security_group_rules.add(rule_obj2)
+ TEST.security_group_rules.add(rule_obj3)
+
+ sec_group_1.rules = [rule_obj]
+ sec_group_2.rules = [rule_obj]
+ TEST.security_groups.add(sec_group_1, sec_group_2)
+
+ # Security Group Rules
+
+ # Quota Sets
+ quota_data = dict(metadata_items='1',
+ injected_file_content_bytes='1',
+ volumes='1',
+ gigabytes='1000',
+ ram=10000,
+ floating_ips='1',
+ instances='10',
+ injected_files='1',
+ cores='10')
+ quota = quotas.QuotaSet(quotas.QuotaSetManager(None), quota_data)
+ TEST.quotas.add(quota)
+
+ # Quota Usages
+ TEST.quota_usages.add({'gigabytes': {'available': 1000,
+ 'used': 0,
+ 'quota': 1000},
+ 'instances': {'available': 10,
+ 'used': 0,
+ 'quota': 10},
+ 'ram': {'available': 10000,
+ 'used': 0,
+ 'quota': 10000},
+ 'cores': {'available': 20,
+ 'used': 0,
+ 'quota': 20}})
+
+ # Servers
+ vals = {"host": "http://nova.example.com:8774",
+ "name": "server_1",
+ "status": "ACTIVE",
+ "tenant_id": TEST.tenants.first().id,
+ "user_id": TEST.user.id,
+ "server_id": "1",
+ "flavor_id": flavor_1.id,
+ "image_id": TEST.images.first().id,
+ "key_name": keypair.name}
+ server_1 = servers.Server(servers.ServerManager(None),
+ json.loads(SERVER_DATA % vals)['server'])
+ vals.update({"name": "server_2",
+ "status": "BUILD",
+ "server_id": "2"})
+ server_2 = servers.Server(servers.ServerManager(None),
+ json.loads(SERVER_DATA % vals)['server'])
+ TEST.servers.add(server_1, server_2)
+
+ # VNC Console Data
+ console = {u'console': {u'url': u'http://example.com:6080/vnc_auto.html',
+ u'type': u'novnc'}}
+ TEST.servers.console_data = console
+ # Floating IPs
+ fip_1 = floating_ips.FloatingIP(floating_ips.FloatingIPManager(None),
+ {'id': 1,
+ 'fixed_ip': '10.0.0.4',
+ 'instance_id': server_1.id,
+ 'ip': '58.58.58.58'})
+ fip_2 = floating_ips.FloatingIP(floating_ips.FloatingIPManager(None),
+ {'id': 2,
+ 'fixed_ip': None,
+ 'instance_id': None,
+ 'ip': '58.58.58.58'})
+ TEST.floating_ips.add(fip_1, fip_2)
+
+ # Usage
+ usage_vals = {"tenant_id": TEST.tenant.id,
+ "instance_name": server_1.name,
+ "flavor_name": flavor_1.name,
+ "flavor_vcpus": flavor_1.vcpus,
+ "flavor_disk": flavor_1.disk,
+ "flavor_ram": flavor_1.ram}
+ usage_obj = usage.Usage(usage.UsageManager(None),
+ json.loads(USAGE_DATA % usage_vals))
+ TEST.usages.add(usage_obj)
+
+ volume_snapshot = vol_snaps.Snapshot(vol_snaps.SnapshotManager(None),
+ {'id': 2,
+ 'display_name': 'test snapshot',
+ 'display_description': 'vol snap!',
+ 'size': 40,
+ 'status': 'available',
+ 'volume_id': 1})
+ TEST.volume_snapshots.add(volume_snapshot)
+
+ cert_data = {'private_key': 'private',
+ 'data': 'certificate_data'}
+ certificate = certs.Certificate(certs.CertificateManager(None), cert_data)
+ TEST.certs.add(certificate)
diff --git a/openstack_dashboard/test/test_data/quantum_data.py b/openstack_dashboard/test/test_data/quantum_data.py
new file mode 100644
index 000000000..23b896fd9
--- /dev/null
+++ b/openstack_dashboard/test/test_data/quantum_data.py
@@ -0,0 +1,111 @@
+# Copyright 2012 Nebula, Inc.
+#
+# 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 copy
+
+from openstack_dashboard.api.quantum import Network, Subnet, Port
+
+from .utils import TestDataContainer
+
+
+def data(TEST):
+ # data returned by openstack_dashboard.api.quantum wrapper
+ TEST.networks = TestDataContainer()
+ TEST.subnets = TestDataContainer()
+ TEST.ports = TestDataContainer()
+
+ # data return by quantumclient
+ TEST.api_networks = TestDataContainer()
+ TEST.api_subnets = TestDataContainer()
+ TEST.api_ports = TestDataContainer()
+
+ # 1st network
+ network_dict = {'admin_state_up': True,
+ 'id': '82288d84-e0a5-42ac-95be-e6af08727e42',
+ 'name': 'net1',
+ 'status': 'ACTIVE',
+ 'subnets': ['e8abc972-eb0c-41f1-9edd-4bc6e3bcd8c9'],
+ 'tenant_id': '1',
+ 'shared': False}
+ subnet_dict = {'allocation_pools': [{'end': '10.0.0.254',
+ 'start': '10.0.0.2'}],
+ 'cidr': '10.0.0.0/24',
+ 'enable_dhcp': True,
+ 'gateway_ip': '10.0.0.1',
+ 'id': network_dict['subnets'][0],
+ 'ip_version': 4,
+ 'name': 'mysubnet1',
+ 'network_id': network_dict['id'],
+ 'tenant_id': network_dict['tenant_id']}
+ port_dict = {'admin_state_up': True,
+ 'device_id': 'af75c8e5-a1cc-4567-8d04-44fcd6922890',
+ 'fixed_ips': [{'ip_address': '10.0.0.3',
+ 'subnet_id': subnet_dict['id']}],
+ 'id': '3ec7f3db-cb2f-4a34-ab6b-69a64d3f008c',
+ 'mac_address': 'fa:16:3e:9c:d5:7e',
+ 'name': '',
+ 'network_id': network_dict['id'],
+ 'status': 'ACTIVE',
+ 'tenant_id': network_dict['tenant_id']}
+
+ TEST.api_networks.add(network_dict)
+ TEST.api_subnets.add(subnet_dict)
+ TEST.api_ports.add(port_dict)
+
+ network = copy.deepcopy(network_dict)
+ subnet = Subnet(subnet_dict)
+ network['subnets'] = [subnet]
+ TEST.networks.add(Network(network))
+ TEST.subnets.add(subnet)
+ TEST.ports.add(Port(port_dict))
+
+ # 2nd network
+ network_dict = {'admin_state_up': True,
+ 'id': '72c3ab6c-c80f-4341-9dc5-210fa31ac6c2',
+ 'name': 'net2',
+ 'status': 'ACTIVE',
+ 'subnets': ['3f7c5d79-ee55-47b0-9213-8e669fb03009'],
+ 'tenant_id': '2',
+ 'shared': True}
+ subnet_dict = {'allocation_pools': [{'end': '172.16.88.254',
+ 'start': '172.16.88.2'}],
+ 'cidr': '172.16.88.0/24',
+ 'enable_dhcp': True,
+ 'gateway_ip': '172.16.88.1',
+ 'id': '3f7c5d79-ee55-47b0-9213-8e669fb03009',
+ 'ip_version': 4,
+ 'name': 'aaaa',
+ 'network_id': network_dict['id'],
+ 'tenant_id': network_dict['tenant_id']}
+ port_dict = {'admin_state_up': True,
+ 'device_id': '40e536b1-b9fd-4eb7-82d6-84db5d65a2ac',
+ 'fixed_ips': [{'ip_address': '172.16.88.3',
+ 'subnet_id': subnet_dict['id']}],
+ 'id': '7e6ce62c-7ea2-44f8-b6b4-769af90a8406',
+ 'mac_address': 'fa:16:3e:56:e6:2f',
+ 'name': '',
+ 'network_id': network_dict['id'],
+ 'status': 'ACTIVE',
+ 'tenant_id': network_dict['tenant_id']}
+
+ TEST.api_networks.add(network_dict)
+ TEST.api_subnets.add(subnet_dict)
+ TEST.api_ports.add(port_dict)
+
+ network = copy.deepcopy(network_dict)
+ subnet = Subnet(subnet_dict)
+ network['subnets'] = [subnet]
+ TEST.networks.add(Network(network))
+ TEST.subnets.add(subnet)
+ TEST.ports.add(Port(port_dict))
diff --git a/openstack_dashboard/test/test_data/swift_data.py b/openstack_dashboard/test/test_data/swift_data.py
new file mode 100644
index 000000000..11fc2e034
--- /dev/null
+++ b/openstack_dashboard/test/test_data/swift_data.py
@@ -0,0 +1,39 @@
+# Copyright 2012 Nebula, Inc.
+#
+# 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 openstack_dashboard.api import swift
+from .utils import TestDataContainer
+
+
+def data(TEST):
+ TEST.containers = TestDataContainer()
+ TEST.objects = TestDataContainer()
+
+ container_1 = swift.Container(dict(name=u"container_one\u6346"))
+ container_2 = swift.Container(dict(name=u"container_two\u6346"))
+ TEST.containers.add(container_1, container_2)
+
+ object_dict = {"name": u"test_object\u6346",
+ "content_type": u"text/plain",
+ "bytes": 128,
+ "last_modified": None,
+ "hash": u"object_hash"}
+ obj_dicts = [object_dict]
+ obj_data = "Fake Data"
+
+ for obj_dict in obj_dicts:
+ swift_object = swift.StorageObject(obj_dict,
+ container_1.name,
+ data=obj_data)
+ TEST.objects.add(swift_object)
diff --git a/openstack_dashboard/test/test_data/utils.py b/openstack_dashboard/test/test_data/utils.py
new file mode 100644
index 000000000..28f6147f1
--- /dev/null
+++ b/openstack_dashboard/test/test_data/utils.py
@@ -0,0 +1,126 @@
+# Copyright 2012 Nebula, Inc.
+#
+# 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.
+
+
+def load_test_data(load_onto=None):
+ from . import exceptions
+ from . import glance_data
+ from . import keystone_data
+ from . import nova_data
+ from . import quantum_data
+ from . import swift_data
+
+ # The order of these loaders matters, some depend on others.
+ loaders = (exceptions.data,
+ keystone_data.data,
+ glance_data.data,
+ nova_data.data,
+ quantum_data.data,
+ swift_data.data)
+ if load_onto:
+ for data_func in loaders:
+ data_func(load_onto)
+ return load_onto
+ else:
+ return TestData(*loaders)
+
+
+class TestData(object):
+ """
+ Holder object for test data. Any functions passed to the init method
+ will be called with the ``TestData`` object as their only argument. They
+ can then load data onto the object as desired.
+
+ The idea is to use the instantiated object like this::
+
+ >>> import glance_data
+ >>> TEST = TestData(glance_data.data)
+ >>> TEST.images.list()
+ ... [<Image: visible_image>, <Image: invisible_image>]
+ >>> TEST.images.first()
+ ... <Image: visible_image>
+
+ You can load as little or as much data as you like as long as the loaders
+ don't conflict with each other.
+
+ See the :class:`~horizon.tests.test_data.utils.TestDataContainer` class
+ for a list of available methods.
+ """
+ def __init__(self, *args):
+ for data_func in args:
+ data_func(self)
+
+
+class TestDataContainer(object):
+ """ A container for test data objects.
+
+ The behavior of this class is meant to mimic a "manager" class, which
+ has convenient shortcuts for common actions like "list", "filter", "get",
+ and "add".
+ """
+ def __init__(self):
+ self._objects = []
+
+ def add(self, *args):
+ """ Add a new object to this container.
+
+ Generally this method should only be used during data loading, since
+ adding data during a test can affect the results of other tests.
+ """
+ for obj in args:
+ if obj not in self._objects:
+ self._objects.append(obj)
+
+ def list(self):
+ """ Returns a list of all objects in this container. """
+ return self._objects
+
+ def filter(self, filtered=None, **kwargs):
+ """
+ Returns objects in this container whose attributes match the given
+ keyword arguments.
+ """
+ if filtered is None:
+ filtered = self._objects
+ try:
+ key, value = kwargs.popitem()
+ except KeyError:
+ # We're out of filters, return
+ return filtered
+
+ def get_match(obj):
+ return hasattr(obj, key) and getattr(obj, key) == value
+
+ return self.filter(filtered=filter(get_match, filtered), **kwargs)
+
+ def get(self, **kwargs):
+ """
+ Returns the single object in this container whose attributes match
+ the given keyword arguments. An error will be raised if the arguments
+ provided don't return exactly one match.
+ """
+ matches = self.filter(**kwargs)
+ if not matches:
+ raise Exception("No matches found.")
+ elif len(matches) > 1:
+ raise Exception("Multiple matches found.")
+ else:
+ return matches.pop()
+
+ def first(self):
+ """ Returns the first object from this container. """
+ return self._objects[0]
+
+ def count(self):
+ return len(self._objects)
diff --git a/openstack_dashboard/test/tests/selenium.py b/openstack_dashboard/test/tests/selenium.py
new file mode 100644
index 000000000..83db95e6b
--- /dev/null
+++ b/openstack_dashboard/test/tests/selenium.py
@@ -0,0 +1,24 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 horizon.test import helpers as test
+
+
+class BrowserTests(test.SeleniumTestCase):
+ def test_splash(self):
+ self.selenium.get(self.live_server_url)
+ button = self.selenium.find_element_by_tag_name("button")
+ self.assertEqual(button.text, "Sign In")
diff --git a/openstack_dashboard/urls.py b/openstack_dashboard/urls.py
index 6d1a55e41..2865902d6 100644
--- a/openstack_dashboard/urls.py
+++ b/openstack_dashboard/urls.py
@@ -31,9 +31,10 @@ import horizon
urlpatterns = patterns('',
- url(r'^$', 'horizon.views.splash', name='splash'),
+ url(r'^$', 'openstack_dashboard.views.splash', name='splash'),
url(r'^auth/', include('openstack_auth.urls')),
- url(r'', include(horizon.urls)))
+ url(r'', include(horizon.urls))
+)
# Development static app and project media serving using the staticfiles app.
urlpatterns += staticfiles_urlpatterns()
diff --git a/openstack_dashboard/usage/__init__.py b/openstack_dashboard/usage/__init__.py
new file mode 100644
index 000000000..e74fc056a
--- /dev/null
+++ b/openstack_dashboard/usage/__init__.py
@@ -0,0 +1,19 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 .base import BaseUsage, TenantUsage, GlobalUsage, almost_now
+from .views import UsageView
+from .tables import BaseUsageTable, TenantUsageTable, GlobalUsageTable
diff --git a/openstack_dashboard/usage/base.py b/openstack_dashboard/usage/base.py
new file mode 100644
index 000000000..a2293ab9f
--- /dev/null
+++ b/openstack_dashboard/usage/base.py
@@ -0,0 +1,156 @@
+from __future__ import division
+
+from calendar import monthrange
+import datetime
+import logging
+
+from django.utils.translation import ugettext as _
+from django.utils import timezone
+
+from horizon import exceptions
+from horizon import forms
+from horizon import messages
+
+from openstack_dashboard import api
+
+
+LOG = logging.getLogger(__name__)
+
+
+def almost_now(input_time):
+ now = timezone.make_naive(timezone.now(), timezone.utc)
+ # If we're less than a minute apart we'll assume success here.
+ return now - input_time < datetime.timedelta(seconds=30)
+
+
+class BaseUsage(object):
+ show_terminated = False
+
+ def __init__(self, request, tenant_id=None):
+ self.tenant_id = tenant_id or request.user.tenant_id
+ self.request = request
+ self.summary = {}
+ self.usage_list = []
+ self.quotas = {}
+
+ @property
+ def today(self):
+ return timezone.now()
+
+ @staticmethod
+ def get_start(year, month, day=1):
+ start = datetime.datetime(year, month, day, 0, 0, 0)
+ return timezone.make_aware(start, timezone.utc)
+
+ @staticmethod
+ def get_end(year, month, day=1):
+ days_in_month = monthrange(year, month)[1]
+ period = datetime.timedelta(days=days_in_month)
+ end = BaseUsage.get_start(year, month, day) + period
+ # End our calculation at midnight of the given day.
+ date_end = datetime.datetime.combine(end, datetime.time(0, 0, 0))
+ date_end = timezone.make_aware(date_end, timezone.utc)
+ if date_end > timezone.now():
+ date_end = timezone.now()
+ return date_end
+
+ def get_instances(self):
+ instance_list = []
+ [instance_list.extend(u.server_usages) for u in self.usage_list]
+ return instance_list
+
+ def get_date_range(self):
+ if not hasattr(self, "start") or not hasattr(self, "end"):
+ args = (self.today.year, self.today.month)
+ form = self.get_form()
+ if form.is_valid():
+ args = (int(form.cleaned_data['year']),
+ int(form.cleaned_data['month']))
+ self.start = self.get_start(*args)
+ self.end = self.get_end(*args)
+ return self.start, self.end
+
+ def get_form(self):
+ if not hasattr(self, 'form'):
+ if any(key in ['month', 'year'] for key in self.request.GET):
+ # bound form
+ self.form = forms.DateForm(self.request.GET)
+ else:
+ # non-bound form
+ self.form = forms.DateForm(initial={'month': self.today.month,
+ 'year': self.today.year})
+ return self.form
+
+ def get_usage_list(self, start, end):
+ raise NotImplementedError("You must define a get_usage method.")
+
+ def summarize(self, start, end):
+ if start <= end <= self.today:
+ # The API can't handle timezone aware datetime, so convert back
+ # to naive UTC just for this last step.
+ start = timezone.make_naive(start, timezone.utc)
+ end = timezone.make_naive(end, timezone.utc)
+ try:
+ self.usage_list = self.get_usage_list(start, end)
+ except:
+ exceptions.handle(self.request,
+ _('Unable to retrieve usage information.'))
+ else:
+ messages.info(self.request,
+ _("You are viewing data for the future, "
+ "which may or may not exist."))
+
+ for tenant_usage in self.usage_list:
+ tenant_summary = tenant_usage.get_summary()
+ for key, value in tenant_summary.items():
+ self.summary.setdefault(key, 0)
+ self.summary[key] += value
+
+ def get_quotas(self):
+ try:
+ self.quotas = api.nova.tenant_quota_usages(self.request)
+ except:
+ exceptions.handle(self.request,
+ _("Unable to retrieve quota information."))
+
+ def csv_link(self):
+ form = self.get_form()
+ if hasattr(form, "cleaned_data"):
+ data = form.cleaned_data
+ else:
+ data = {"month": self.today.month, "year": self.today.year}
+ return "?month=%s&year=%s&format=csv" % (data['month'], data['year'])
+
+
+class GlobalUsage(BaseUsage):
+ show_terminated = True
+
+ def get_usage_list(self, start, end):
+ return api.usage_list(self.request, start, end)
+
+
+class TenantUsage(BaseUsage):
+ attrs = ('memory_mb', 'vcpus', 'uptime',
+ 'hours', 'local_gb')
+
+ def get_usage_list(self, start, end):
+ show_terminated = self.request.GET.get('show_terminated',
+ self.show_terminated)
+ instances = []
+ terminated_instances = []
+ usage = api.usage_get(self.request, self.tenant_id, start, end)
+ # Attribute may not exist if there are no instances
+ if hasattr(usage, 'server_usages'):
+ now = self.today
+ for server_usage in usage.server_usages:
+ # This is a way to phrase uptime in a way that is compatible
+ # with the 'timesince' filter. (Use of local time intentional.)
+ server_uptime = server_usage['uptime']
+ total_uptime = now - datetime.timedelta(seconds=server_uptime)
+ server_usage['uptime_at'] = total_uptime
+ if server_usage['ended_at'] and not show_terminated:
+ terminated_instances.append(server_usage)
+ else:
+ instances.append(server_usage)
+ usage.server_usages = instances
+ return (usage,)
diff --git a/openstack_dashboard/usage/tables.py b/openstack_dashboard/usage/tables.py
new file mode 100644
index 000000000..a679e1344
--- /dev/null
+++ b/openstack_dashboard/usage/tables.py
@@ -0,0 +1,71 @@
+from django.core import urlresolvers
+from django.utils.translation import ugettext_lazy as _
+from django.template.defaultfilters import timesince, floatformat
+
+from horizon import tables
+from horizon.templatetags.sizeformat import mbformat
+
+
+class CSVSummary(tables.LinkAction):
+ name = "csv_summary"
+ verbose_name = _("Download CSV Summary")
+ classes = ("btn-download",)
+
+ def get_link_url(self, usage=None):
+ return self.table.kwargs['usage'].csv_link()
+
+
+class BaseUsageTable(tables.DataTable):
+ vcpus = tables.Column('vcpus', verbose_name=_("VCPUs"))
+ disk = tables.Column('local_gb', verbose_name=_("Disk"))
+ memory = tables.Column('memory_mb',
+ verbose_name=_("RAM"),
+ filters=(mbformat,),
+ attrs={"data-type": "size"})
+ hours = tables.Column('vcpu_hours', verbose_name=_("VCPU Hours"),
+ filters=(lambda v: floatformat(v, 2),))
+
+
+class GlobalUsageTable(BaseUsageTable):
+ tenant = tables.Column('tenant_name', verbose_name=_("Project Name"))
+ disk_hours = tables.Column('disk_gb_hours',
+ verbose_name=_("Disk GB Hours"),
+ filters=(lambda v: floatformat(v, 2),))
+
+ def get_object_id(self, datum):
+ return datum.tenant_id
+
+ class Meta:
+ name = "global_usage"
+ verbose_name = _("Usage Summary")
+ columns = ("tenant", "vcpus", "disk", "memory",
+ "hours", "disk_hours")
+ table_actions = (CSVSummary,)
+ multi_select = False
+
+
+def get_instance_link(datum):
+ view = "horizon:nova:instances:detail"
+ if datum.get('instance_id', False):
+ return urlresolvers.reverse(view, args=(datum.get('instance_id'),))
+ else:
+ return None
+
+
+class TenantUsageTable(BaseUsageTable):
+ instance = tables.Column('name',
+ verbose_name=_("Instance Name"),
+ link=get_instance_link)
+ uptime = tables.Column('uptime_at',
+ verbose_name=_("Uptime"),
+ filters=(timesince,))
+
+ def get_object_id(self, datum):
+ return datum.get('instance_id', id(datum))
+
+ class Meta:
+ name = "tenant_usage"
+ verbose_name = _("Usage Summary")
+ columns = ("instance", "vcpus", "disk", "memory", "uptime")
+ table_actions = (CSVSummary,)
+ multi_select = False
diff --git a/openstack_dashboard/usage/views.py b/openstack_dashboard/usage/views.py
new file mode 100644
index 000000000..bb6cf635c
--- /dev/null
+++ b/openstack_dashboard/usage/views.py
@@ -0,0 +1,54 @@
+import logging
+
+from horizon import tables
+from .base import BaseUsage
+
+
+LOG = logging.getLogger(__name__)
+
+
+class UsageView(tables.DataTableView):
+ usage_class = None
+ show_terminated = True
+
+ def __init__(self, *args, **kwargs):
+ super(UsageView, self).__init__(*args, **kwargs)
+ if not issubclass(self.usage_class, BaseUsage):
+ raise AttributeError("You must specify a usage_class attribute "
+ "which is a subclass of BaseUsage.")
+
+ def get_template_names(self):
+ if self.request.GET.get('format', 'html') == 'csv':
+ return ".".join((self.template_name.rsplit('.', 1)[0], 'csv'))
+ return self.template_name
+
+ def get_content_type(self):
+ if self.request.GET.get('format', 'html') == 'csv':
+ return "text/csv"
+ return "text/html"
+
+ def get_data(self):
+ tenant_id = self.kwargs.get('tenant_id', self.request.user.tenant_id)
+ self.usage = self.usage_class(self.request, tenant_id)
+ self.usage.summarize(*self.usage.get_date_range())
+ self.usage.get_quotas()
+ self.kwargs['usage'] = self.usage
+ return self.usage.usage_list
+
+ def get_context_data(self, **kwargs):
+ context = super(UsageView, self).get_context_data(**kwargs)
+ context['table'].kwargs['usage'] = self.usage
+ context['form'] = self.usage.form
+ context['usage'] = self.usage
+ return context
+
+ def render_to_response(self, context, **response_kwargs):
+ resp = self.response_class(request=self.request,
+ template=self.get_template_names(),
+ context=context,
+ content_type=self.get_content_type(),
+ **response_kwargs)
+ if self.request.GET.get('format', 'html') == 'csv':
+ resp['Content-Disposition'] = 'attachment; filename=usage.csv'
+ resp['Content-Type'] = 'text/csv'
+ return resp
diff --git a/openstack_dashboard/views.py b/openstack_dashboard/views.py
new file mode 100644
index 000000000..75227e690
--- /dev/null
+++ b/openstack_dashboard/views.py
@@ -0,0 +1,38 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Nebula, Inc.
+#
+# 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 import shortcuts
+from django.views.decorators import vary
+
+import horizon
+
+from openstack_auth.views import Login
+
+
+def get_user_home(user):
+ if user.is_superuser:
+ return horizon.get_dashboard('admin').get_absolute_url()
+ return horizon.get_dashboard('project').get_absolute_url()
+
+
+@vary.vary_on_cookie
+def splash(request):
+ if request.user.is_authenticated():
+ return shortcuts.redirect(get_user_home(request.user))
+ form = Login(request)
+ request.session.clear()
+ request.session.set_test_cookie()
+ return shortcuts.render(request, 'splash.html', {'form': form})