Commit e155a219 by Szabolcs Gelencser

Add initial template details view

parent 29ed5533
......@@ -2,8 +2,13 @@
<project version="4">
<component name="ChangeListManager">
<list default="true" id="1fbec8af-5a7c-40f9-b994-83ac07d1ae1d" name="Default" comment="">
<change beforePath="$PROJECT_DIR$/circle/circle/db.sqlite3" afterPath="$PROJECT_DIR$/circle/circle/db.sqlite3" />
<change beforePath="$PROJECT_DIR$/circle/vm/models/instance.py" afterPath="$PROJECT_DIR$/circle/vm/models/instance.py" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
<change beforePath="$PROJECT_DIR$/circle/circle/os_policies/circle_policy.json" afterPath="$PROJECT_DIR$/circle/circle/os_policies/circle_policy.json" />
<change beforePath="$PROJECT_DIR$/circle/dashboard/forms.py" afterPath="$PROJECT_DIR$/circle/dashboard/forms.py" />
<change beforePath="$PROJECT_DIR$/circle/dashboard/templates/dashboard/template-edit.html" afterPath="$PROJECT_DIR$/circle/dashboard/templates/dashboard/template-edit.html" />
<change beforePath="$PROJECT_DIR$/circle/dashboard/urls.py" afterPath="$PROJECT_DIR$/circle/dashboard/urls.py" />
<change beforePath="$PROJECT_DIR$/circle/dashboard/views/template.py" afterPath="$PROJECT_DIR$/circle/dashboard/views/template.py" />
<change beforePath="$PROJECT_DIR$/circle/dashboard/views/util.py" afterPath="$PROJECT_DIR$/circle/dashboard/views/util.py" />
</list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="TRACKING_ENABLED" value="true" />
......@@ -12,6 +17,9 @@
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="CoverageDataManager">
<SUITE FILE_PATH="coverage/cloud$operations.coverage" NAME="operations Coverage Results" MODIFIED="1521451585654" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/circle/common" />
</component>
<component name="DatabaseView">
<option name="SHOW_INTERMEDIATE" value="true" />
<option name="GROUP_DATA_SOURCES" value="true" />
......@@ -29,61 +37,84 @@
</component>
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file leaf-file-name="vm.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/circle/dashboard/views/vm.py">
<file leaf-file-name="template.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/circle/dashboard/views/template.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="405">
<caret line="485" column="37" lean-forward="false" selection-start-line="485" selection-start-column="37" selection-end-line="485" selection-end-column="37" />
<folding>
<element signature="e#731#787#0" expanded="true" />
<marker date="1521452159522" expanded="true" signature="10052:10265" ph="SELECT count... vm_instance" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="template-edit.html" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/circle/dashboard/templates/dashboard/template-edit.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="216">
<caret line="107" column="81" lean-forward="false" selection-start-line="107" selection-start-column="66" selection-end-line="107" selection-end-column="81" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="glance_policy.json" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/circle/circle/os_policies/glance_policy.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="344">
<caret line="1168" column="0" lean-forward="true" selection-start-line="1168" selection-start-column="0" selection-end-line="1168" selection-end-column="0" />
<state relative-caret-position="340">
<caret line="20" column="21" lean-forward="true" selection-start-line="20" selection-start-column="21" selection-end-line="20" selection-end-column="21" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="instance.py" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/circle/vm/models/instance.py">
<file leaf-file-name="nova_policy.json" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/circle/circle/os_policies/nova_policy.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="463">
<caret line="143" column="49" lean-forward="true" selection-start-line="143" selection-start-column="49" selection-end-line="143" selection-end-column="49" />
<state relative-caret-position="216">
<caret line="379" column="25" lean-forward="false" selection-start-line="379" selection-start-column="20" selection-end-line="379" selection-end-column="25" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="client.py" pinned="false" current-in-tab="false">
<entry file="file://$USER_HOME$/.virtualenvs/cloud/local/lib/python2.7/site-packages/novaclient/client.py">
<file leaf-file-name="circle_policy.json" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/circle/circle/os_policies/circle_policy.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="233">
<caret line="82" column="0" lean-forward="false" selection-start-line="82" selection-start-column="0" selection-end-line="82" selection-end-column="0" />
<state relative-caret-position="51">
<caret line="3" column="27" lean-forward="false" selection-start-line="3" selection-start-column="27" selection-end-line="3" selection-end-column="27" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="instance_tags.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/circle/dashboard/templatetags/instance_tags.py">
<file leaf-file-name="urls.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/circle/dashboard/urls.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="575">
<caret line="36" column="43" lean-forward="true" selection-start-line="36" selection-start-column="43" selection-end-line="36" selection-end-column="43" />
<state relative-caret-position="221">
<caret line="42" column="43" lean-forward="false" selection-start-line="42" selection-start-column="43" selection-end-line="42" selection-end-column="43" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="operations.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/circle/common/operations.py">
<file leaf-file-name="vm.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/circle/dashboard/views/vm.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="429">
<caret line="242" column="0" lean-forward="false" selection-start-line="242" selection-start-column="0" selection-end-line="242" selection-end-column="0" />
<state relative-caret-position="131">
<caret line="99" column="8" lean-forward="true" selection-start-line="99" selection-start-column="8" selection-end-line="99" selection-end-column="8" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="nova.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/circle/openstack_api/nova.py">
<file leaf-file-name="util.py" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/circle/dashboard/views/util.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="225">
<caret line="310" column="0" lean-forward="false" selection-start-line="310" selection-start-column="0" selection-end-line="310" selection-end-column="0" />
<state relative-caret-position="255">
<caret line="602" column="0" lean-forward="true" selection-start-line="602" selection-start-column="0" selection-end-line="602" selection-end-column="0" />
<folding />
</state>
</provider>
......@@ -101,19 +132,6 @@
</component>
<component name="FindInProjectRecents">
<findStrings>
<find>instan</find>
<find>monkey</find>
<find>_os_server</find>
<find>get_from_os</find>
<find>OperationView(</find>
<find>get_abl</find>
<find>vmaddinter</find>
<find>addinterface</find>
<find>shut</find>
<find>addinterfac</find>
<find>detailview</find>
<find>get_object</find>
<find>class server</find>
<find>vmdetail</find>
<find>policy</find>
<find>vm_ops</find>
......@@ -123,7 +141,6 @@
<find>compute:</find>
<find>wtf</find>
<find>True</find>
<find>template</find>
<find>saveas</find>
<find>save</find>
<find>template-list</find>
......@@ -131,6 +148,20 @@
<find>class instancetemplate</find>
<find>reverse</find>
<find>vmcreate</find>
<find>template-dele</find>
<find>TemplateDelete</find>
<find>DeleteViewBase</find>
<find>TransferTemplateOwnershipConfirmView</find>
<find>template</find>
<find>TransferOwnershipConfirmView</find>
<find>template-transfer-ownership</find>
<find>TransferTemplateOwnershipView</find>
<find>TransferOwnershipView</find>
<find>context_is_admin</find>
<find>service</find>
<find>template-access</find>
<find>get_</find>
<find>image</find>
</findStrings>
<replaceStrings>
<replace>'ACTIVE'</replace>
......@@ -148,8 +179,6 @@
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/circle/openstack_api/policy.py" />
<option value="$PROJECT_DIR$/circle/dashboard/templates/dashboard/vm-plain-image-create.html" />
<option value="$PROJECT_DIR$/circle/request/urls.py" />
<option value="$PROJECT_DIR$/circle/dashboard/templates/dashboard/index-vxlans.html" />
<option value="$PROJECT_DIR$/circle/openstack_api/base.py" />
......@@ -184,21 +213,23 @@
<option value="$PROJECT_DIR$/circle/dashboard/templates/dashboard/vm-detail/home.html" />
<option value="$PROJECT_DIR$/circle/dashboard/templates/dashboard/vm-detail/console.html" />
<option value="$PROJECT_DIR$/circle/common/operations.py" />
<option value="$PROJECT_DIR$/circle/dashboard/forms.py" />
<option value="$PROJECT_DIR$/circle/dashboard/templates/dashboard/vm-detail/network.html" />
<option value="$PROJECT_DIR$/circle/dashboard/views/util.py" />
<option value="$PROJECT_DIR$/circle/openstack_api/nova.py" />
<option value="$PROJECT_DIR$/circle/circle/settings/base.py" />
<option value="$PROJECT_DIR$/circle/circle/os_policies/circle_policy.json" />
<option value="$PROJECT_DIR$/circle/vm/operations.py" />
<option value="$PROJECT_DIR$/circle/dashboard/templates/dashboard/index.html" />
<option value="$PROJECT_DIR$/circle/dashboard/views/template.py" />
<option value="$PROJECT_DIR$/circle/dashboard/templates/dashboard/index-templates.html" />
<option value="$PROJECT_DIR$/circle/dashboard/views/index.py" />
<option value="$PROJECT_DIR$/circle/dashboard/urls.py" />
<option value="$PROJECT_DIR$/circle/dashboard/templatetags/instance_tags.py" />
<option value="$PROJECT_DIR$/circle/dashboard/views/vm.py" />
<option value="$PROJECT_DIR$/circle/vm/models/instance.py" />
<option value="$PROJECT_DIR$/circle/dashboard/forms.py" />
<option value="$PROJECT_DIR$/circle/dashboard/templates/dashboard/template-edit.html" />
<option value="$PROJECT_DIR$/circle/dashboard/views/util.py" />
<option value="$PROJECT_DIR$/circle/dashboard/views/template.py" />
<option value="$PROJECT_DIR$/circle/dashboard/urls.py" />
<option value="$PROJECT_DIR$/circle/circle/os_policies/glance_policy.json" />
<option value="$PROJECT_DIR$/circle/circle/os_policies/circle_policy.json" />
</list>
</option>
</component>
......@@ -272,14 +303,20 @@
<item name="cloud" type="b2602c69:ProjectViewProjectNode" />
<item name="cloud" type="462c0819:PsiDirectoryNode" />
<item name="circle" type="462c0819:PsiDirectoryNode" />
<item name="dashboard" type="462c0819:PsiDirectoryNode" />
<item name="circle" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="cloud" type="b2602c69:ProjectViewProjectNode" />
<item name="cloud" type="462c0819:PsiDirectoryNode" />
<item name="circle" type="462c0819:PsiDirectoryNode" />
<item name="circle" type="462c0819:PsiDirectoryNode" />
<item name="os_policies" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="cloud" type="b2602c69:ProjectViewProjectNode" />
<item name="cloud" type="462c0819:PsiDirectoryNode" />
<item name="circle" type="462c0819:PsiDirectoryNode" />
<item name="dashboard" type="462c0819:PsiDirectoryNode" />
<item name="templatetags" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="cloud" type="b2602c69:ProjectViewProjectNode" />
......@@ -290,8 +327,8 @@
<select />
</subPane>
</pane>
<pane id="Scratches" />
<pane id="Scope" />
<pane id="Scratches" />
</panes>
</component>
<component name="PropertiesComponent">
......@@ -300,7 +337,7 @@
<property name="settings.editor.selected.configurable" value="watcher.settings" />
<property name="NewWatcherDialog.advanced.open" value="true" />
<property name="DefaultHtmlFileTemplate" value="HTML File" />
<property name="SearchEverywhereHistoryKey" value="instancetemp&#9;null&#9;null&#10;instancetem&#9;null&#9;null&#10;url&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/urls.py&#10;vmcreate&#9;null&#9;null&#10;index&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/views/index.py&#10;base&#9;FILE&#9;file:///home/h3yduck/cloud/circle/circle/settings/base.py&#10;opera&#9;FILE&#9;file:///home/h3yduck/cloud/circle/vm/operations.py&#10;operations&#9;FILE&#9;file:///home/h3yduck/cloud/circle/common/operations.py&#10;templat&#9;null&#9;null&#10;vmadd&#9;null&#9;null&#10;vmdetail&#9;null&#9;null&#10;addinterfa&#9;null&#9;null&#10;addin&#9;null&#9;null&#10;server&#9;null&#9;null&#10;Instance&#9;null&#9;null&#10;instance&#9;FILE&#9;file:///home/h3yduck/cloud/circle/vm/models/instance.py&#10;operat&#9;null&#9;null&#10;ins&#9;FILE&#9;file:///home/h3yduck/cloud/circle/vm/models/instance.py&#10;vmdetai&#9;null&#9;null&#10;operationvi&#9;null&#9;null&#10;ser&#9;null&#9;null&#10;server.&#9;FILE&#9;file:///home/h3yduck/.virtualenvs/cloud/local/lib/python2.7/site-packages/novaclient/v2/servers.py&#10;resources.&#9;FILE&#9;file:///home/h3yduck/cloud/circle/request/templates/request/initials/resources.html&#10;vm-de&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/templates/dashboard/vm-detail.html&#10;vxla&#9;null&#9;null&#10;urls&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/urls.py&#10;index-v&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/templates/dashboard/index-vxlans.html&#10;index-vm&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/templates/dashboard/index-vm.html&#10;vmdeta&#9;null&#9;null&#10;create&#9;FILE&#9;file:///home/h3yduck/cloud/circle/network/templates/network/vxlan-create.html&#10;vxl&#9;null&#9;null&#10;nov&#9;FILE&#9;file:///home/h3yduck/cloud/circle/openstack_api/nova.py&#10;nova.p&#9;FILE&#9;file:///home/h3yduck/cloud/circle/openstack_api/nova.py&#10;vmdetailv&#9;null&#9;null&#10;editor&#9;null&#9;null&#10;networktopo&#9;FILE&#9;file:///home/h3yduck/cloud/circle/network/static/js/horizon.networktopology.js&#10;bow&#9;FILE&#9;file:///home/h3yduck/cloud/circle/bower.json&#10;base.py&#9;FILE&#9;file:///home/h3yduck/cloud/circle/circle/settings/base.py&#10;local&#9;null&#9;null&#10;vnc&#9;null&#9;null&#10;plain&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/templates/dashboard/vm-plain-image-create.html&#10;forms&#9;null&#9;null&#10;vxlanform&#9;null&#9;null&#10;instanc&#9;FILE&#9;file:///home/h3yduck/cloud/circle/vm/models/instance.py&#10;index-vxla&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/templates/dashboard/index-vxlans.html&#10;_vm-c&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/templates/dashboard/_vm-create-1.html&#10;vmcrea&#9;null&#9;null&#10;loginV&#9;null&#9;null&#10;index.html&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/templates/dashboard/index.html&#10;sleep&#9;null&#9;null" />
<property name="SearchEverywhereHistoryKey" value="vmdeta&#9;null&#9;null&#10;templatedet&#9;null&#9;null&#10;instancetemp&#9;null&#9;null&#10;instancetem&#9;null&#9;null&#10;url&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/urls.py&#10;vmcreate&#9;null&#9;null&#10;index&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/views/index.py&#10;base&#9;FILE&#9;file:///home/h3yduck/cloud/circle/circle/settings/base.py&#10;opera&#9;FILE&#9;file:///home/h3yduck/cloud/circle/vm/operations.py&#10;operations&#9;FILE&#9;file:///home/h3yduck/cloud/circle/common/operations.py&#10;templat&#9;null&#9;null&#10;vmadd&#9;null&#9;null&#10;vmdetail&#9;null&#9;null&#10;addinterfa&#9;null&#9;null&#10;addin&#9;null&#9;null&#10;server&#9;null&#9;null&#10;Instance&#9;null&#9;null&#10;instance&#9;FILE&#9;file:///home/h3yduck/cloud/circle/vm/models/instance.py&#10;operat&#9;null&#9;null&#10;ins&#9;FILE&#9;file:///home/h3yduck/cloud/circle/vm/models/instance.py&#10;vmdetai&#9;null&#9;null&#10;operationvi&#9;null&#9;null&#10;ser&#9;null&#9;null&#10;server.&#9;FILE&#9;file:///home/h3yduck/.virtualenvs/cloud/local/lib/python2.7/site-packages/novaclient/v2/servers.py&#10;resources.&#9;FILE&#9;file:///home/h3yduck/cloud/circle/request/templates/request/initials/resources.html&#10;vm-de&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/templates/dashboard/vm-detail.html&#10;vxla&#9;null&#9;null&#10;urls&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/urls.py&#10;index-v&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/templates/dashboard/index-vxlans.html&#10;index-vm&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/templates/dashboard/index-vm.html&#10;create&#9;FILE&#9;file:///home/h3yduck/cloud/circle/network/templates/network/vxlan-create.html&#10;vxl&#9;null&#9;null&#10;nov&#9;FILE&#9;file:///home/h3yduck/cloud/circle/openstack_api/nova.py&#10;nova.p&#9;FILE&#9;file:///home/h3yduck/cloud/circle/openstack_api/nova.py&#10;vmdetailv&#9;null&#9;null&#10;editor&#9;null&#9;null&#10;networktopo&#9;FILE&#9;file:///home/h3yduck/cloud/circle/network/static/js/horizon.networktopology.js&#10;bow&#9;FILE&#9;file:///home/h3yduck/cloud/circle/bower.json&#10;base.py&#9;FILE&#9;file:///home/h3yduck/cloud/circle/circle/settings/base.py&#10;local&#9;null&#9;null&#10;vnc&#9;null&#9;null&#10;plain&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/templates/dashboard/vm-plain-image-create.html&#10;forms&#9;null&#9;null&#10;vxlanform&#9;null&#9;null&#10;instanc&#9;FILE&#9;file:///home/h3yduck/cloud/circle/vm/models/instance.py&#10;index-vxla&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/templates/dashboard/index-vxlans.html&#10;_vm-c&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/templates/dashboard/_vm-create-1.html&#10;vmcrea&#9;null&#9;null&#10;loginV&#9;null&#9;null&#10;index.html&#9;FILE&#9;file:///home/h3yduck/cloud/circle/dashboard/templates/dashboard/index.html" />
</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
......@@ -322,7 +359,7 @@
</list>
</option>
</component>
<component name="RunManager" selected="Python.operations">
<component name="RunManager" selected="Django server.circlestack">
<configuration name="index" type="PythonConfigurationType" factoryName="Python" temporary="true">
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
......@@ -426,21 +463,21 @@
<editor active="true" />
<layout>
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32980973" sideWeight="0.4978701" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.327818" sideWeight="0.5021299" order="7" side_tool="true" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32769555" sideWeight="0.514377" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Python Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.43023255" sideWeight="0.43610224" order="7" side_tool="true" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32769555" sideWeight="0.49574015" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.23150106" sideWeight="0.48988286" order="7" side_tool="true" content_ui="tabs" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.18051118" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.23150106" sideWeight="0.49201277" order="7" side_tool="true" content_ui="tabs" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.1682641" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
<window_info id="Docker" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="8" side_tool="false" content_ui="tabs" />
<window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32980973" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="SciView" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.23150106" sideWeight="0.5101172" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.23150106" sideWeight="0.5079872" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
......@@ -522,7 +559,7 @@
</properties>
</breakpoint>
</default-breakpoints>
<option name="time" value="235" />
<option name="time" value="236" />
</breakpoint-manager>
<watches-manager />
</component>
......@@ -567,6 +604,11 @@
</expressions>
<expressions id="evaluateExpression">
<expression>
<expression-string>self.request.user</expression-string>
<language-id>Python</language-id>
<evaluation-mode>EXPRESSION</evaluation-mode>
</expression>
<expression>
<expression-string>instances</expression-string>
<language-id>Python</language-id>
<evaluation-mode>EXPRESSION</evaluation-mode>
......@@ -606,59 +648,13 @@
<language-id>Python</language-id>
<evaluation-mode>EXPRESSION</evaluation-mode>
</expression>
<expression>
<expression-string>openstack_api.neutron.port_list_list(self.request)</expression-string>
<language-id>Python</language-id>
<evaluation-mode>EXPRESSION</evaluation-mode>
</expression>
</expressions>
</component>
<component name="editorHistoryManager">
<entry file="file://$APPLICATION_HOME_DIR$/helpers/typeshed/stdlib/2/typing.pyi">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="195">
<caret line="225" column="8" lean-forward="false" selection-start-line="225" selection-start-column="8" selection-end-line="225" selection-end-column="8" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.virtualenvs/cloud/local/lib/python2.7/site-packages/django/dispatch/dispatcher.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="195">
<caret line="192" column="0" lean-forward="false" selection-start-line="192" selection-start-column="0" selection-end-line="192" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/network/templates/network/vxlan-create.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="335">
<caret line="25" column="53" lean-forward="false" selection-start-line="25" selection-start-column="53" selection-end-line="25" selection-end-column="53" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/circle/os_policies/neutron_policy.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="178">
<caret line="117" column="28" lean-forward="false" selection-start-line="117" selection-start-column="19" selection-end-line="117" selection-end-column="28" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/circle/os_policies/nova_policy.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="178">
<caret line="50" column="29" lean-forward="false" selection-start-line="50" selection-start-column="20" selection-end-line="50" selection-end-column="29" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/dashboard/templates/dashboard/index-vxlans.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
......@@ -666,7 +662,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="476">
<caret line="55" column="31" lean-forward="true" selection-start-line="55" selection-start-column="31" selection-end-line="55" selection-end-column="31" />
<folding />
</state>
</provider>
</entry>
......@@ -674,7 +669,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="459">
<caret line="70" column="29" lean-forward="false" selection-start-line="70" selection-start-column="29" selection-end-line="70" selection-end-column="29" />
<folding />
</state>
</provider>
</entry>
......@@ -682,7 +676,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="280">
<caret line="973" column="23" lean-forward="false" selection-start-line="973" selection-start-column="4" selection-end-line="973" selection-end-column="23" />
<folding />
</state>
</provider>
</entry>
......@@ -690,7 +683,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
......@@ -698,7 +690,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="493">
<caret line="29" column="110" lean-forward="true" selection-start-line="29" selection-start-column="110" selection-end-line="29" selection-end-column="110" />
<folding />
</state>
</provider>
</entry>
......@@ -706,7 +697,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
......@@ -714,7 +704,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="340">
<caret line="22" column="0" lean-forward="false" selection-start-line="22" selection-start-column="0" selection-end-line="30" selection-end-column="42" />
<folding />
</state>
</provider>
</entry>
......@@ -722,7 +711,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1192">
<caret line="1233" column="41" lean-forward="false" selection-start-line="1233" selection-start-column="41" selection-end-line="1233" selection-end-column="41" />
<folding />
</state>
</provider>
</entry>
......@@ -730,7 +718,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="272">
<caret line="17" column="26" lean-forward="true" selection-start-line="17" selection-start-column="26" selection-end-line="17" selection-end-column="26" />
<folding />
</state>
</provider>
</entry>
......@@ -738,7 +725,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="306">
<caret line="104" column="0" lean-forward="false" selection-start-line="104" selection-start-column="0" selection-end-line="104" selection-end-column="45" />
<folding />
</state>
</provider>
</entry>
......@@ -746,7 +732,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="374">
<caret line="22" column="44" lean-forward="true" selection-start-line="22" selection-start-column="44" selection-end-line="22" selection-end-column="44" />
<folding />
</state>
</provider>
</entry>
......@@ -754,7 +739,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="153">
<caret line="9" column="11" lean-forward="true" selection-start-line="9" selection-start-column="11" selection-end-line="9" selection-end-column="11" />
<folding />
</state>
</provider>
</entry>
......@@ -762,7 +746,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-243">
<caret line="114" column="27" lean-forward="false" selection-start-line="114" selection-start-column="27" selection-end-line="114" selection-end-column="27" />
<folding />
</state>
</provider>
</entry>
......@@ -770,7 +753,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="170">
<caret line="84" column="13" lean-forward="false" selection-start-line="84" selection-start-column="13" selection-end-line="84" selection-end-column="65" />
<folding />
</state>
</provider>
</entry>
......@@ -778,7 +760,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="476">
<caret line="28" column="20" lean-forward="true" selection-start-line="28" selection-start-column="20" selection-end-line="28" selection-end-column="20" />
<folding />
</state>
</provider>
</entry>
......@@ -786,7 +767,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="-663">
<caret line="33" column="45" lean-forward="false" selection-start-line="33" selection-start-column="30" selection-end-line="33" selection-end-column="45" />
<folding />
</state>
</provider>
</entry>
......@@ -794,7 +774,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="183">
<caret line="114" column="0" lean-forward="false" selection-start-line="114" selection-start-column="0" selection-end-line="114" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
......@@ -802,7 +781,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="306">
<caret line="1158" column="8" lean-forward="false" selection-start-line="1158" selection-start-column="8" selection-end-line="1158" selection-end-column="8" />
<folding />
</state>
</provider>
</entry>
......@@ -810,15 +788,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="0">
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/dashboard/forms.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="162">
<caret line="982" column="46" lean-forward="true" selection-start-line="982" selection-start-column="46" selection-end-line="982" selection-end-column="46" />
<folding />
</state>
</provider>
</entry>
......@@ -826,7 +795,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="213">
<caret line="1818" column="37" lean-forward="false" selection-start-line="1818" selection-start-column="31" selection-end-line="1818" selection-end-column="37" />
<folding />
</state>
</provider>
</entry>
......@@ -834,7 +802,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="256">
<caret line="133" column="8" lean-forward="false" selection-start-line="133" selection-start-column="8" selection-end-line="133" selection-end-column="8" />
<folding />
</state>
</provider>
</entry>
......@@ -842,15 +809,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="247">
<caret line="1220" column="37" lean-forward="false" selection-start-line="1220" selection-start-column="37" selection-end-line="1220" selection-end-column="37" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/dashboard/views/util.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="93">
<caret line="389" column="38" lean-forward="false" selection-start-line="389" selection-start-column="38" selection-end-line="389" selection-end-column="38" />
<folding />
</state>
</provider>
</entry>
......@@ -858,7 +816,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="173">
<caret line="80" column="11" lean-forward="false" selection-start-line="80" selection-start-column="5" selection-end-line="80" selection-end-column="11" />
<folding />
</state>
</provider>
</entry>
......@@ -866,7 +823,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="289">
<caret line="17" column="32" lean-forward="false" selection-start-line="17" selection-start-column="28" selection-end-line="17" selection-end-column="32" />
<folding />
</state>
</provider>
</entry>
......@@ -874,7 +830,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="289">
<caret line="55" column="2" lean-forward="false" selection-start-line="55" selection-start-column="2" selection-end-line="55" selection-end-column="2" />
<folding />
</state>
</provider>
</entry>
......@@ -882,15 +837,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="306">
<caret line="142" column="4" lean-forward="false" selection-start-line="142" selection-start-column="4" selection-end-line="142" selection-end-column="4" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/circle/os_policies/circle_policy.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="51">
<caret line="3" column="0" lean-forward="true" selection-start-line="3" selection-start-column="0" selection-end-line="3" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
......@@ -906,7 +852,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="590">
<caret line="149" column="19" lean-forward="true" selection-start-line="149" selection-start-column="19" selection-end-line="149" selection-end-column="19" />
<folding />
</state>
</provider>
</entry>
......@@ -914,7 +859,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="204">
<caret line="17" column="6" lean-forward="false" selection-start-line="17" selection-start-column="6" selection-end-line="17" selection-end-column="6" />
<folding />
</state>
</provider>
</entry>
......@@ -922,17 +866,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="550">
<caret line="535" column="65" lean-forward="true" selection-start-line="535" selection-start-column="65" selection-end-line="535" selection-end-column="65" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/dashboard/views/template.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="233">
<caret line="43" column="1" lean-forward="true" selection-start-line="43" selection-start-column="1" selection-end-line="43" selection-end-column="1" />
<folding>
<marker date="1520950390987" expanded="true" signature="9980:10193" ph="SELECT count... vm_instance" />
</folding>
</state>
</provider>
</entry>
......@@ -940,7 +873,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="102">
<caret line="62" column="23" lean-forward="false" selection-start-line="62" selection-start-column="23" selection-end-line="62" selection-end-column="23" />
<folding />
</state>
</provider>
</entry>
......@@ -948,7 +880,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="267">
<caret line="24" column="17" lean-forward="false" selection-start-line="24" selection-start-column="17" selection-end-line="24" selection-end-column="17" />
<folding />
</state>
</provider>
</entry>
......@@ -956,7 +887,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="437">
<caret line="35" column="36" lean-forward="false" selection-start-line="35" selection-start-column="36" selection-end-line="35" selection-end-column="36" />
<folding />
</state>
</provider>
</entry>
......@@ -964,15 +894,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="233">
<caret line="135" column="15" lean-forward="false" selection-start-line="135" selection-start-column="15" selection-end-line="135" selection-end-column="69" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/dashboard/urls.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="420">
<caret line="59" column="36" lean-forward="false" selection-start-line="59" selection-start-column="14" selection-end-line="59" selection-end-column="36" />
<folding />
</state>
</provider>
</entry>
......@@ -980,7 +901,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="429">
<caret line="242" column="0" lean-forward="false" selection-start-line="242" selection-start-column="0" selection-end-line="242" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
......@@ -988,7 +908,6 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="233">
<caret line="82" column="0" lean-forward="false" selection-start-line="82" selection-start-column="0" selection-end-line="82" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
......@@ -996,30 +915,110 @@
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="225">
<caret line="310" column="0" lean-forward="false" selection-start-line="310" selection-start-column="0" selection-end-line="310" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/dashboard/templatetags/instance_tags.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="575">
<caret line="36" column="43" lean-forward="true" selection-start-line="36" selection-start-column="43" selection-end-line="36" selection-end-column="43" />
<caret line="36" column="43" lean-forward="false" selection-start-line="36" selection-start-column="43" selection-end-line="36" selection-end-column="43" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/vm/models/instance.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="293">
<caret line="148" column="15" lean-forward="true" selection-start-line="148" selection-start-column="15" selection-end-line="148" selection-end-column="15" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/dashboard/forms.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="153">
<caret line="537" column="9" lean-forward="true" selection-start-line="537" selection-start-column="9" selection-end-line="537" selection-end-column="9" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$USER_HOME$/.virtualenvs/cloud/local/lib/python2.7/site-packages/django/views/generic/edit.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="716">
<caret line="286" column="6" lean-forward="false" selection-start-line="286" selection-start-column="6" selection-end-line="286" selection-end-column="6" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/dashboard/views/util.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="255">
<caret line="602" column="0" lean-forward="true" selection-start-line="602" selection-start-column="0" selection-end-line="602" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/dashboard/urls.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="221">
<caret line="42" column="43" lean-forward="false" selection-start-line="42" selection-start-column="43" selection-end-line="42" selection-end-column="43" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/dashboard/views/vm.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="344">
<caret line="1168" column="0" lean-forward="true" selection-start-line="1168" selection-start-column="0" selection-end-line="1168" selection-end-column="0" />
<state relative-caret-position="131">
<caret line="99" column="8" lean-forward="true" selection-start-line="99" selection-start-column="8" selection-end-line="99" selection-end-column="8" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/vm/models/instance.py">
<entry file="file://$PROJECT_DIR$/circle/dashboard/views/template.py">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="463">
<caret line="143" column="49" lean-forward="true" selection-start-line="143" selection-start-column="49" selection-end-line="143" selection-end-column="49" />
<state relative-caret-position="405">
<caret line="485" column="37" lean-forward="false" selection-start-line="485" selection-start-column="37" selection-end-line="485" selection-end-column="37" />
<folding>
<element signature="e#731#787#0" expanded="true" />
<marker date="1521452159522" expanded="true" signature="10052:10265" ph="SELECT count... vm_instance" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/circle/os_policies/keystone_policy.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="187">
<caret line="11" column="0" lean-forward="true" selection-start-line="11" selection-start-column="0" selection-end-line="11" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/dashboard/templates/dashboard/template-edit.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="216">
<caret line="107" column="81" lean-forward="false" selection-start-line="107" selection-start-column="66" selection-end-line="107" selection-end-column="81" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/circle/os_policies/nova_policy.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="216">
<caret line="379" column="25" lean-forward="false" selection-start-line="379" selection-start-column="20" selection-end-line="379" selection-end-column="25" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/circle/os_policies/glance_policy.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="340">
<caret line="20" column="21" lean-forward="true" selection-start-line="20" selection-start-column="21" selection-end-line="20" selection-end-column="21" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/circle/circle/os_policies/circle_policy.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="51">
<caret line="3" column="27" lean-forward="false" selection-start-line="3" selection-start-column="27" selection-end-line="3" selection-end-column="27" />
<folding />
</state>
</provider>
......
{
"admin_or_owner": "is_admin:True or (role:admin and is_admin_project:True) or project_id:%(project_id)s",
"default": "rule:admin_or_owner",
"template:create": ""
"template:create": "rule:admin_or_owner"
}
\ No newline at end of file
......@@ -502,77 +502,77 @@ class NodeForm(forms.ModelForm):
class TemplateForm(forms.ModelForm):
networks = forms.ModelMultipleChoiceField(
queryset=None, required=False, label=_("Networks"))
num_cores = forms.IntegerField(widget=forms.NumberInput(attrs={
'class': "form-control input-tags cpu-count-input",
'min': 1,
'max': 10,
'required': "",
}),
min_value=1, max_value=10,
)
ram_size = forms.IntegerField(widget=forms.NumberInput(attrs={
'class': "form-control input-tags ram-input",
'min': 128,
'max': MAX_NODE_RAM,
'step': 128,
'required': "",
}),
min_value=128, max_value=MAX_NODE_RAM,
)
priority = forms.ChoiceField(priority_choices, widget=forms.Select(attrs={
'class': "form-control input-tags cpu-priority-input",
}))
# networks = forms.ModelMultipleChoiceField(queryset=None, required=False, label=_("Networks"))
#
# num_cores = forms.IntegerField(widget=forms.NumberInput(attrs={
# 'class': "form-control input-tags cpu-count-input",
# 'min': 1,
# 'max': 10,
# 'required': "",
# }),
# min_value=1, max_value=10,
# )
#
# ram_size = forms.IntegerField(widget=forms.NumberInput(attrs={
# 'class': "form-control input-tags ram-input",
# 'min': 128,
# 'max': MAX_NODE_RAM,
# 'step': 128,
# 'required': "",
# }),
# min_value=128, max_value=MAX_NODE_RAM,
# )
#
# priority = forms.ChoiceField(priority_choices, widget=forms.Select(attrs={
# 'class': "form-control input-tags cpu-priority-input",
# }))
name = forms.TextInput()
flavor = forms.ChoiceField(['a','b','c'])
def __init__(self, *args, **kwargs):
self.user = kwargs.pop("user", None)
super(TemplateForm, self).__init__(*args, **kwargs)
self.fields['networks'].queryset = Vlan.get_objects_with_level(
'user', self.user)
data = self.data.copy()
data['owner'] = self.user.pk
self.data = data
if self.instance.pk:
n = self.instance.interface_set.values_list("vlan", flat=True)
self.initial['networks'] = n
if self.instance.pk and not self.instance.has_level(self.user,
'owner'):
self.allowed_fields = ()
else:
self.allowed_fields = (
'name', 'access_method', 'description', 'system', 'tags',
'arch', 'lease', 'has_agent')
if (self.user.has_perm('vm.change_template_resources') or
not self.instance.pk):
self.allowed_fields += tuple(set(self.fields.keys()) -
set(['raw_data']))
if self.user.is_superuser:
self.allowed_fields += ('raw_data', )
for name, field in self.fields.items():
if name not in self.allowed_fields:
field.widget.attrs['disabled'] = 'disabled'
if not self.instance.pk and len(self.errors) < 1:
self.initial['num_cores'] = 1
self.initial['priority'] = 10
self.initial['ram_size'] = 512
self.initial['max_ram_size'] = 512
lease_queryset = (
Lease.get_objects_with_level("operator", self.user).distinct() |
Lease.objects.filter(pk=self.instance.lease_id).distinct())
self.fields["lease"].queryset = lease_queryset
self.fields['raw_data'].validators.append(domain_validator)
#
# self.fields['networks'].queryset = ()#Vlan.get_objects_with_level('user', self.user)
#
# data = self.data.copy()
# data['owner'] = self.user.pk
# self.data = data
#
# if self.instance.pk:
# n = self.instance.interface_set.values_list("vlan", flat=True)
# self.initial['networks'] = n
#
# if self.instance.pk and not self.instance.has_level(self.user, 'owner'):
# self.allowed_fields = ()
# else:
# self.allowed_fields = (
# 'name', 'access_method', 'description', 'system', 'tags',
# 'arch', 'lease', 'has_agent')
# if (self.user.has_perm('vm.change_template_resources') or
# not self.instance.pk):
# self.allowed_fields += tuple(set(self.fields.keys()) -
# set(['raw_data']))
# if self.user.is_superuser:
# self.allowed_fields += ('raw_data', )
# for name, field in self.fields.items():
# if name not in self.allowed_fields:
# field.widget.attrs['disabled'] = 'disabled'
#
# if not self.instance.pk and len(self.errors) < 1:
# self.initial['num_cores'] = 1
# self.initial['priority'] = 10
# self.initial['ram_size'] = 512
# self.initial['max_ram_size'] = 512
#
# lease_queryset = (
# Lease.get_objects_with_level("operator", self.user).distinct() |
# Lease.objects.filter(pk=self.instance.lease_id).distinct())
#
# self.fields["lease"].queryset = lease_queryset
#
# self.fields['raw_data'].validators.append(domain_validator)
def clean_owner(self):
if self.instance.pk is not None:
......
......@@ -39,26 +39,26 @@
<fieldset class="resources-sliders">
<legend>{% trans "Resource configuration" %}</legend>
{% include "dashboard/_resources-sliders.html" with field_priority=form.priority field_num_cores=form.num_cores field_ram_size=form.ram_size %}
{{ form.max_ram_size|as_crispy_field }}
{# {{ form.max_ram_size|as_crispy_field }}#}
</fieldset>
<fieldset>
<legend>{% trans "Virtual machine settings" %}</legend>
{{ form.arch|as_crispy_field }}
{{ form.access_method|as_crispy_field }}
{{ form.boot_menu|as_crispy_field }}
{{ form.raw_data|as_crispy_field }}
{{ form.req_traits|as_crispy_field }}
{{ form.description|as_crispy_field }}
{{ form.system|as_crispy_field }}
{{ form.has_agent|as_crispy_field }}
{# {{ form.arch|as_crispy_field }}#}
{# {{ form.access_method|as_crispy_field }}#}
{# {{ form.boot_menu|as_crispy_field }}#}
{# {{ form.raw_data|as_crispy_field }}#}
{# {{ form.req_traits|as_crispy_field }}#}
{# {{ form.description|as_crispy_field }}#}
{# {{ form.system|as_crispy_field }}#}
{# {{ form.has_agent|as_crispy_field }}#}
</fieldset>
<fieldset>
<legend>{% trans "External resources" %}</legend>
{{ form.networks|as_crispy_field }}
{{ form.lease|as_crispy_field }}
{{ form.tags|as_crispy_field }}
{# {{ form.networks|as_crispy_field }}#}
{# {{ form.lease|as_crispy_field }}#}
{##}
{# {{ form.tags|as_crispy_field }}#}
</fieldset>
<input type="submit" value="{% trans "Save changes" %}" class="btn btn-primary">
......
......@@ -18,7 +18,8 @@
from __future__ import absolute_import
from dashboard.views.autocomplete import AclUserGroupAutocomplete, AclUserAutocomplete
from dashboard.views.template import TemplateList, TemplateChoose, TemplateDetail
from dashboard.views.template import TemplateList, TemplateChoose, TemplateDetail, TemplateDelete, \
TransferTemplateOwnershipConfirmView, TransferTemplateOwnershipView
from dashboard.views.vm import VmDetailView, VmList, VmCreate, vm_activity, vm_ops, FavouriteView, VmPlainImageCreate
from django.conf.urls import url
......@@ -52,10 +53,10 @@ urlpatterns = [
name='dashboard.views.template-detail'),
url(r"^template/list/$", TemplateList.as_view(),
name="dashboard.views.template-list"),
# url(r"^template/delete/(?P<pk>\d+)/$", TemplateDelete.as_view(),
# name="dashboard.views.template-delete"),
# url(r'^template/(?P<pk>\d+)/tx/$', TransferTemplateOwnershipView.as_view(),
# name='dashboard.views.template-transfer-ownership'),
url(r"^template/delete/(?P<pk>\d+)/$", TemplateDelete.as_view(),
name="dashboard.views.template-delete"),
url(r'^template/(?P<pk>\d+)/tx/$', TransferTemplateOwnershipView.as_view(),
name='dashboard.views.template-transfer-ownership'),
url(r'^vm/(?P<pk>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/$', VmDetailView.as_view(),
name='dashboard.views.detail'),
# url(r'^vm/(?P<pk>\d+)/vnctoken/$', VmDetailVncTokenView.as_view(),
......@@ -88,9 +89,9 @@ urlpatterns = [
# url(r'^vm/tx/(?P<key>.*)/?$',
# TransferInstanceOwnershipConfirmView.as_view(),
# name='dashboard.views.vm-transfer-ownership-confirm'),
# url(r'^template/tx/(?P<key>.*)/?$',
# TransferTemplateOwnershipConfirmView.as_view(),
# name='dashboard.views.template-transfer-ownership-confirm'),
url(r'^template/tx/(?P<key>.*)/?$',
TransferTemplateOwnershipConfirmView.as_view(),
name='dashboard.views.template-transfer-ownership-confirm'),
# url(r'^node/delete/(?P<pk>\d+)/$', NodeDelete.as_view(),
# name="dashboard.views.delete-node"),
# url(r'^node/(?P<pk>\d+)/activity/$', NodeActivityView.as_view(),
......
......@@ -53,8 +53,8 @@ from .util import (
AclUpdateView, FilterMixin,
# TransferOwnershipConfirmView, TransferOwnershipView,
# DeleteViewBase,
GraphMixin
)
GraphMixin,
DeleteViewBase, TransferOwnershipConfirmView, TransferOwnershipView)
logger = logging.getLogger(__name__)
......@@ -285,22 +285,21 @@ class TemplateList(LoginRequiredMixin, FilterMixin, SingleTableView):
return qs.select_related("lease", "owner", "owner__profile")
#
# class TemplateDelete(DeleteViewBase):
# model = InstanceTemplate
# success_message = _("Template successfully deleted.")
#
# def get_success_url(self):
# return reverse("dashboard.views.template-list")
#
# def delete_obj(self, request, *args, **kwargs):
# object = self.get_object()
# object.destroy_disks()
# object.delete()
class TemplateDelete(DeleteViewBase):
model = InstanceTemplate
success_message = _("Template successfully deleted.")
def get_success_url(self):
return reverse("dashboard.views.template-list")
def delete_obj(self, request, *args, **kwargs):
object = self.get_object()
object.destroy_disks()
object.delete()
class TemplateDetail(LoginRequiredMixin, GraphMixin,
SuccessMessageMixin, UpdateView):
class TemplateDetail(LoginRequiredMixin, GraphMixin, SuccessMessageMixin, UpdateView):
model = InstanceTemplate
template_name = "dashboard/template-edit.html"
form_class = TemplateForm
......@@ -308,8 +307,11 @@ class TemplateDetail(LoginRequiredMixin, GraphMixin,
def get(self, request, *args, **kwargs):
template = self.get_object()
if not template.has_level(request.user, 'user'):
#TODO: multiple users
if template.owner_id != request.user.id:
raise PermissionDenied()
if request.is_ajax():
template = {
'num_cores': template.num_cores,
......@@ -334,15 +336,15 @@ class TemplateDetail(LoginRequiredMixin, GraphMixin,
return super(TemplateDetail, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
obj = self.get_object()
template = self.get_object()
context = super(TemplateDetail, self).get_context_data(**kwargs)
context['acl'] = AclUpdateView.get_acl_data(
obj, self.request.user, 'dashboard.views.template-acl')
context['disks'] = obj.disks.all()
context['is_owner'] = obj.has_level(self.request.user, 'owner')
# context['acl'] = AclUpdateView.get_acl_data(
# template, self.request.user, 'dashboard.views.template-acl')
# context['disks'] = template.disks.all()
context['is_owner'] = template.owner_id == self.request.user.id
context['aclform'] = AclUserOrGroupAddForm()
context['parent'] = obj.parent
context['show_graph'] = obj.has_level(self.request.user, 'operator')
# context['parent'] = template.parent
# context['show_graph'] = template.has_level(self.request.user, 'operator')
return context
def get_success_url(self):
......@@ -476,18 +478,18 @@ class LeaseDetail(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
# object.delete()
#
#
# class TransferTemplateOwnershipConfirmView(TransferOwnershipConfirmView):
# template = "dashboard/confirm/transfer-template-ownership.html"
# model = InstanceTemplate
#
#
# class TransferTemplateOwnershipView(TransferOwnershipView):
# confirm_view = TransferTemplateOwnershipConfirmView
# model = InstanceTemplate
# notification_msg = ugettext_noop(
# '%(owner)s offered you to take the ownership of '
# 'his/her template called %(instance)s. '
# '<a href="%(token)s" '
# 'class="btn btn-success btn-small">Accept</a>')
# token_url = 'dashboard.views.template-transfer-ownership-confirm'
# template = "dashboard/template-tx-owner.html"
class TransferTemplateOwnershipConfirmView(TransferOwnershipConfirmView):
template = "dashboard/confirm/transfer-template-ownership.html"
model = InstanceTemplate
class TransferTemplateOwnershipView(TransferOwnershipView):
confirm_view = TransferTemplateOwnershipConfirmView
model = InstanceTemplate
notification_msg = ugettext_noop(
'%(owner)s offered you to take the ownership of '
'his/her template called %(instance)s. '
'<a href="%(token)s" '
'class="btn btn-success btn-small">Accept</a>')
token_url = 'dashboard.views.template-transfer-ownership-confirm'
template = "dashboard/template-tx-owner.html"
......@@ -595,175 +595,175 @@ class GraphMixin(object):
# return urljoin(settings.DJANGO_URL, url)
#
#
# class TransferOwnershipView(CheckedDetailView, DetailView):
# def get_template_names(self):
# if self.request.is_ajax():
# return ['dashboard/_modal.html']
# else:
# return ['dashboard/nojs-wrapper.html']
#
# def get_context_data(self, *args, **kwargs):
# context = super(TransferOwnershipView, self).get_context_data(
# *args, **kwargs)
# context['form'] = TransferOwnershipForm()
# context.update({
# 'box_title': _("Transfer ownership"),
# 'ajax_title': True,
# 'template': self.template,
# })
# return context
#
# def post(self, request, *args, **kwargs):
# form = TransferOwnershipForm(request.POST)
# if not form.is_valid():
# return self.get(request)
# try:
# new_owner = search_user(request.POST['name'])
# except User.DoesNotExist:
# messages.error(request, _('Can not find specified user.'))
# return self.get(request, *args, **kwargs)
# except KeyError:
# raise SuspiciousOperation()
#
# obj = self.get_object()
# if not (obj.owner == request.user or
# request.user.is_superuser):
# raise PermissionDenied()
#
# token = signing.dumps(
# (obj.pk, new_owner.pk),
# salt=self.confirm_view.get_salt())
# token_path = reverse(self.token_url, args=[token])
# try:
# new_owner.profile.notify(
# ugettext_noop('Ownership offer'),
# self.notification_msg,
# {'instance': obj, 'token': token_path, 'owner': request.user})
# except Profile.DoesNotExist:
# messages.error(request, _('Can not notify selected user.'))
# else:
# messages.success(request,
# _('User %s is notified about the offer.') % (
# unicode(new_owner), ))
#
# return redirect(obj.get_absolute_url())
#
#
# class TransferOwnershipConfirmView(LoginRequiredMixin, View):
# """User can accept an ownership offer."""
#
# max_age = 3 * 24 * 3600
# success_message = _("Ownership successfully transferred to you.")
#
# @classmethod
# def get_salt(cls):
# return unicode(cls) + unicode(cls.model)
#
# def get(self, request, key, *args, **kwargs):
# """Confirm ownership transfer based on token.
# """
# logger.debug('Confirm dialog for token %s.', key)
# try:
# instance, new_owner = self.get_instance(key, request.user)
# except PermissionDenied:
# messages.error(request, _('This token is for an other user.'))
# raise
# except SuspiciousOperation:
# messages.error(request, _('This token is invalid or has expired.'))
# raise PermissionDenied()
# return render(request, self.template,
# dictionary={'instance': instance, 'key': key})
#
# def change_owner(self, instance, new_owner):
# instance.owner = new_owner
# instance.clean()
# instance.save()
#
# def post(self, request, key, *args, **kwargs):
# """Really transfer ownership based on token.
# """
# instance, owner = self.get_instance(key, request.user)
#
# old = instance.owner
# self.change_owner(instance, request.user)
# messages.success(request, self.success_message)
# logger.info('Ownership of %s transferred from %s to %s.',
# unicode(instance), unicode(old), unicode(request.user))
# if old.profile:
# old.profile.notify(
# ugettext_noop('Ownership accepted'),
# ugettext_noop('Your ownership offer of %(instance)s has been '
# 'accepted by %(owner)s.'),
# {'instance': instance, 'owner': request.user})
# return redirect(instance.get_absolute_url())
#
# def get_instance(self, key, user):
# """Get object based on signed token.
# """
# try:
# instance, new_owner = (
# signing.loads(key, max_age=self.max_age,
# salt=self.get_salt()))
# except (signing.BadSignature, ValueError, TypeError) as e:
# logger.error('Tried invalid token. Token: %s, user: %s. %s',
# key, unicode(user), unicode(e))
# raise SuspiciousOperation()
#
# try:
# instance = self.model.objects.get(id=instance)
# except self.model.DoesNotExist as e:
# logger.error('Tried token to nonexistent instance %d. '
# 'Token: %s, user: %s. %s',
# instance, key, unicode(user), unicode(e))
# raise Http404()
#
# if new_owner != user.pk:
# logger.error('%s (%d) tried the token for %s. Token: %s.',
# unicode(user), user.pk, new_owner, key)
# raise PermissionDenied()
# return (instance, new_owner)
#
#
# class DeleteViewBase(LoginRequiredMixin, DeleteView):
# level = 'owner'
#
# def get_template_names(self):
# if self.request.is_ajax():
# return ['dashboard/confirm/ajax-delete.html']
# else:
# return ['dashboard/confirm/base-delete.html']
#
# def check_auth(self):
# if not self.get_object().has_level(self.request.user, self.level):
# raise PermissionDenied()
#
# def get(self, request, *args, **kwargs):
# try:
# self.check_auth()
# except PermissionDenied:
# message = _("Only the owners can delete the selected object.")
# if request.is_ajax():
# raise PermissionDenied()
# else:
# messages.warning(request, message)
# return redirect(self.get_success_url())
# return super(DeleteViewBase, self).get(request, *args, **kwargs)
#
# def delete_obj(self, request, *args, **kwargs):
# self.get_object().delete()
#
# def delete(self, request, *args, **kwargs):
# self.check_auth()
# self.delete_obj(request, *args, **kwargs)
#
# if request.is_ajax():
# return HttpResponse(
# json.dumps({'message': self.success_message}),
# content_type="application/json",
# )
# else:
# messages.success(request, self.success_message)
# return HttpResponseRedirect(self.get_success_url())
class TransferOwnershipView(CheckedDetailView, DetailView):
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/_modal.html']
else:
return ['dashboard/nojs-wrapper.html']
def get_context_data(self, *args, **kwargs):
context = super(TransferOwnershipView, self).get_context_data(
*args, **kwargs)
context['form'] = TransferOwnershipForm()
context.update({
'box_title': _("Transfer ownership"),
'ajax_title': True,
'template': self.template,
})
return context
def post(self, request, *args, **kwargs):
form = TransferOwnershipForm(request.POST)
if not form.is_valid():
return self.get(request)
try:
new_owner = search_user(request.POST['name'])
except User.DoesNotExist:
messages.error(request, _('Can not find specified user.'))
return self.get(request, *args, **kwargs)
except KeyError:
raise SuspiciousOperation()
obj = self.get_object()
if not (obj.owner == request.user or
request.user.is_superuser):
raise PermissionDenied()
token = signing.dumps(
(obj.pk, new_owner.pk),
salt=self.confirm_view.get_salt())
token_path = reverse(self.token_url, args=[token])
try:
new_owner.profile.notify(
ugettext_noop('Ownership offer'),
self.notification_msg,
{'instance': obj, 'token': token_path, 'owner': request.user})
except Profile.DoesNotExist:
messages.error(request, _('Can not notify selected user.'))
else:
messages.success(request,
_('User %s is notified about the offer.') % (
unicode(new_owner), ))
return redirect(obj.get_absolute_url())
class TransferOwnershipConfirmView(LoginRequiredMixin, View):
"""User can accept an ownership offer."""
max_age = 3 * 24 * 3600
success_message = _("Ownership successfully transferred to you.")
@classmethod
def get_salt(cls):
return unicode(cls) + unicode(cls.model)
def get(self, request, key, *args, **kwargs):
"""Confirm ownership transfer based on token.
"""
logger.debug('Confirm dialog for token %s.', key)
try:
instance, new_owner = self.get_instance(key, request.user)
except PermissionDenied:
messages.error(request, _('This token is for an other user.'))
raise
except SuspiciousOperation:
messages.error(request, _('This token is invalid or has expired.'))
raise PermissionDenied()
return render(request, self.template,
dictionary={'instance': instance, 'key': key})
def change_owner(self, instance, new_owner):
instance.owner = new_owner
instance.clean()
instance.save()
def post(self, request, key, *args, **kwargs):
"""Really transfer ownership based on token.
"""
instance, owner = self.get_instance(key, request.user)
old = instance.owner
self.change_owner(instance, request.user)
messages.success(request, self.success_message)
logger.info('Ownership of %s transferred from %s to %s.',
unicode(instance), unicode(old), unicode(request.user))
if old.profile:
old.profile.notify(
ugettext_noop('Ownership accepted'),
ugettext_noop('Your ownership offer of %(instance)s has been '
'accepted by %(owner)s.'),
{'instance': instance, 'owner': request.user})
return redirect(instance.get_absolute_url())
def get_instance(self, key, user):
"""Get object based on signed token.
"""
try:
instance, new_owner = (
signing.loads(key, max_age=self.max_age,
salt=self.get_salt()))
except (signing.BadSignature, ValueError, TypeError) as e:
logger.error('Tried invalid token. Token: %s, user: %s. %s',
key, unicode(user), unicode(e))
raise SuspiciousOperation()
try:
instance = self.model.objects.get(id=instance)
except self.model.DoesNotExist as e:
logger.error('Tried token to nonexistent instance %d. '
'Token: %s, user: %s. %s',
instance, key, unicode(user), unicode(e))
raise Http404()
if new_owner != user.pk:
logger.error('%s (%d) tried the token for %s. Token: %s.',
unicode(user), user.pk, new_owner, key)
raise PermissionDenied()
return (instance, new_owner)
class DeleteViewBase(LoginRequiredMixin, DeleteView):
level = 'owner'
def get_template_names(self):
if self.request.is_ajax():
return ['dashboard/confirm/ajax-delete.html']
else:
return ['dashboard/confirm/base-delete.html']
def check_auth(self):
if not self.get_object().has_level(self.request.user, self.level):
raise PermissionDenied()
def get(self, request, *args, **kwargs):
try:
self.check_auth()
except PermissionDenied:
message = _("Only the owners can delete the selected object.")
if request.is_ajax():
raise PermissionDenied()
else:
messages.warning(request, message)
return redirect(self.get_success_url())
return super(DeleteViewBase, self).get(request, *args, **kwargs)
def delete_obj(self, request, *args, **kwargs):
self.get_object().delete()
def delete(self, request, *args, **kwargs):
self.check_auth()
self.delete_obj(request, *args, **kwargs)
if request.is_ajax():
return HttpResponse(
json.dumps({'message': self.success_message}),
content_type="application/json",
)
else:
messages.success(request, self.success_message)
return HttpResponseRedirect(self.get_success_url())
#
#
# # only in Django 1.9
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment