mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-23 04:22:01 -06:00
Converted site/rack/device import views to new scheme
This commit is contained in:
parent
4a8147f8a5
commit
7e660d4d8e
@ -107,29 +107,34 @@ class SiteForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SiteFromCSVForm(forms.ModelForm):
|
class SiteCSVForm(forms.ModelForm):
|
||||||
region = forms.ModelChoiceField(
|
region = forms.ModelChoiceField(
|
||||||
Region.objects.all(), to_field_name='name', required=False, error_messages={
|
queryset=Region.objects.all(),
|
||||||
'invalid_choice': 'Tenant not found.'
|
required=False,
|
||||||
|
to_field_name='name',
|
||||||
|
help_text='Name of assigned region',
|
||||||
|
error_messages={
|
||||||
|
'invalid_choice': 'Region not found.',
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
tenant = forms.ModelChoiceField(
|
tenant = forms.ModelChoiceField(
|
||||||
Tenant.objects.all(), to_field_name='name', required=False, error_messages={
|
queryset=Tenant.objects.all(),
|
||||||
'invalid_choice': 'Tenant not found.'
|
required=False,
|
||||||
|
to_field_name='name',
|
||||||
|
help_text='Name of assigned tenant',
|
||||||
|
error_messages={
|
||||||
|
'invalid_choice': 'Tenant not found.',
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Site
|
model = Site
|
||||||
fields = [
|
fields = [
|
||||||
'name', 'slug', 'region', 'tenant', 'facility', 'asn', 'contact_name', 'contact_phone', 'contact_email',
|
'name', 'slug', 'region', 'tenant', 'facility', 'asn', 'physical_address', 'shipping_address',
|
||||||
|
'contact_name', 'contact_phone', 'contact_email', 'comments',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class SiteImportForm(BootstrapMixin, BulkImportForm):
|
|
||||||
csv = CSVDataField(csv_form=SiteFromCSVForm)
|
|
||||||
|
|
||||||
|
|
||||||
class SiteBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
class SiteBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=Site.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(queryset=Site.objects.all(), widget=forms.MultipleHiddenInput)
|
||||||
region = TreeNodeChoiceField(queryset=Region.objects.all(), required=False)
|
region = TreeNodeChoiceField(queryset=Region.objects.all(), required=False)
|
||||||
@ -217,35 +222,62 @@ class RackForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class RackFromCSVForm(forms.ModelForm):
|
class RackCSVForm(forms.ModelForm):
|
||||||
site = forms.ModelChoiceField(queryset=Site.objects.all(), to_field_name='name',
|
site = forms.ModelChoiceField(
|
||||||
error_messages={'invalid_choice': 'Site not found.'})
|
queryset=Site.objects.all(),
|
||||||
group_name = forms.CharField(required=False)
|
to_field_name='name',
|
||||||
tenant = forms.ModelChoiceField(Tenant.objects.all(), to_field_name='name', required=False,
|
help_text='Name of parent site',
|
||||||
error_messages={'invalid_choice': 'Tenant not found.'})
|
error_messages={
|
||||||
role = forms.ModelChoiceField(RackRole.objects.all(), to_field_name='name', required=False,
|
'invalid_choice': 'Site not found.',
|
||||||
error_messages={'invalid_choice': 'Role not found.'})
|
}
|
||||||
|
)
|
||||||
|
group = forms.ModelChoiceField(
|
||||||
|
queryset=RackGroup.objects.all(),
|
||||||
|
to_field_name='name',
|
||||||
|
required=False,
|
||||||
|
help_text='Name of parent group',
|
||||||
|
error_messages={
|
||||||
|
'invalid_choice': 'Rack group not found.',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
tenant = forms.ModelChoiceField(
|
||||||
|
queryset=Tenant.objects.all(),
|
||||||
|
required=False,
|
||||||
|
to_field_name='name',
|
||||||
|
help_text='Name of assigned tenant',
|
||||||
|
error_messages={
|
||||||
|
'invalid_choice': 'Tenant not found.',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
role = forms.ModelChoiceField(
|
||||||
|
queryset=RackRole.objects.all(),
|
||||||
|
required=False,
|
||||||
|
to_field_name='name',
|
||||||
|
help_text='Name of assigned role',
|
||||||
|
error_messages={
|
||||||
|
'invalid_choice': 'Role not found.',
|
||||||
|
}
|
||||||
|
)
|
||||||
type = forms.CharField(required=False)
|
type = forms.CharField(required=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Rack
|
model = Rack
|
||||||
fields = ['site', 'group_name', 'name', 'facility_id', 'tenant', 'role', 'type', 'width', 'u_height',
|
fields = [
|
||||||
'desc_units']
|
'site', 'group', 'name', 'facility_id', 'tenant', 'role', 'type', 'width', 'u_height', 'desc_units',
|
||||||
|
]
|
||||||
|
|
||||||
def clean(self):
|
def clean_group(self):
|
||||||
|
|
||||||
site = self.cleaned_data.get('site')
|
site = self.cleaned_data.get('site')
|
||||||
group = self.cleaned_data.get('group_name')
|
group = self.cleaned_data.get('group')
|
||||||
|
|
||||||
# Validate rack group
|
if group and group.site != site:
|
||||||
if site and group:
|
raise ValidationError("Invalid group for site {}: {}".format(site, group))
|
||||||
try:
|
|
||||||
self.instance.group = RackGroup.objects.get(site=site, name=group)
|
|
||||||
except RackGroup.DoesNotExist:
|
|
||||||
self.add_error('group_name', "Invalid rack group ({})".format(group))
|
|
||||||
|
|
||||||
def clean_type(self):
|
def clean_type(self):
|
||||||
|
|
||||||
rack_type = self.cleaned_data['type']
|
rack_type = self.cleaned_data['type']
|
||||||
|
|
||||||
if not rack_type:
|
if not rack_type:
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
@ -258,10 +290,6 @@ class RackFromCSVForm(forms.ModelForm):
|
|||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
class RackImportForm(BootstrapMixin, BulkImportForm):
|
|
||||||
csv = CSVDataField(csv_form=RackFromCSVForm)
|
|
||||||
|
|
||||||
|
|
||||||
class RackBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
class RackBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=Rack.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(queryset=Rack.objects.all(), widget=forms.MultipleHiddenInput)
|
||||||
site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False, label='Site')
|
site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False, label='Site')
|
||||||
@ -663,25 +691,47 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
|||||||
self.initial['rack'] = self.instance.parent_bay.device.rack_id
|
self.initial['rack'] = self.instance.parent_bay.device.rack_id
|
||||||
|
|
||||||
|
|
||||||
class BaseDeviceFromCSVForm(forms.ModelForm):
|
class BaseDeviceCSVForm(forms.ModelForm):
|
||||||
device_role = forms.ModelChoiceField(
|
device_role = forms.ModelChoiceField(
|
||||||
queryset=DeviceRole.objects.all(), to_field_name='name',
|
queryset=DeviceRole.objects.all(),
|
||||||
error_messages={'invalid_choice': 'Invalid device role.'}
|
to_field_name='name',
|
||||||
|
help_text='Name of assigned role',
|
||||||
|
error_messages={
|
||||||
|
'invalid_choice': 'Invalid device role.',
|
||||||
|
}
|
||||||
)
|
)
|
||||||
tenant = forms.ModelChoiceField(
|
tenant = forms.ModelChoiceField(
|
||||||
Tenant.objects.all(), to_field_name='name', required=False,
|
queryset=Tenant.objects.all(),
|
||||||
error_messages={'invalid_choice': 'Tenant not found.'}
|
required=False,
|
||||||
|
to_field_name='name',
|
||||||
|
help_text='Name of assigned tenant',
|
||||||
|
error_messages={
|
||||||
|
'invalid_choice': 'Tenant not found.',
|
||||||
|
}
|
||||||
)
|
)
|
||||||
manufacturer = forms.ModelChoiceField(
|
manufacturer = forms.ModelChoiceField(
|
||||||
queryset=Manufacturer.objects.all(), to_field_name='name',
|
queryset=Manufacturer.objects.all(),
|
||||||
error_messages={'invalid_choice': 'Invalid manufacturer.'}
|
to_field_name='name',
|
||||||
|
help_text='Manufacturer name',
|
||||||
|
error_messages={
|
||||||
|
'invalid_choice': 'Invalid manufacturer.',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
model_name = forms.CharField(
|
||||||
|
help_text='Model name'
|
||||||
)
|
)
|
||||||
model_name = forms.CharField()
|
|
||||||
platform = forms.ModelChoiceField(
|
platform = forms.ModelChoiceField(
|
||||||
queryset=Platform.objects.all(), required=False, to_field_name='name',
|
queryset=Platform.objects.all(),
|
||||||
error_messages={'invalid_choice': 'Invalid platform.'}
|
required=False,
|
||||||
|
to_field_name='name',
|
||||||
|
help_text='Name of assigned platform',
|
||||||
|
error_messages={
|
||||||
|
'invalid_choice': 'Invalid platform.',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
status = forms.CharField(
|
||||||
|
help_text='Status name'
|
||||||
)
|
)
|
||||||
status = forms.CharField()
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = []
|
fields = []
|
||||||
@ -707,16 +757,25 @@ class BaseDeviceFromCSVForm(forms.ModelForm):
|
|||||||
raise ValidationError("Invalid status: {}".format(self.cleaned_data['status']))
|
raise ValidationError("Invalid status: {}".format(self.cleaned_data['status']))
|
||||||
|
|
||||||
|
|
||||||
class DeviceFromCSVForm(BaseDeviceFromCSVForm):
|
class DeviceCSVForm(BaseDeviceCSVForm):
|
||||||
site = forms.ModelChoiceField(
|
site = forms.ModelChoiceField(
|
||||||
queryset=Site.objects.all(), to_field_name='name', error_messages={
|
queryset=Site.objects.all(),
|
||||||
|
to_field_name='name',
|
||||||
|
help_text='Name of parent site',
|
||||||
|
error_messages={
|
||||||
'invalid_choice': 'Invalid site name.',
|
'invalid_choice': 'Invalid site name.',
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
rack_name = forms.CharField(required=False)
|
rack_name = forms.CharField(
|
||||||
face = forms.CharField(required=False)
|
required=False,
|
||||||
|
help_text='Name of parent rack'
|
||||||
|
)
|
||||||
|
face = forms.CharField(
|
||||||
|
required=False,
|
||||||
|
help_text='Mounted rack face (front or rear)'
|
||||||
|
)
|
||||||
|
|
||||||
class Meta(BaseDeviceFromCSVForm.Meta):
|
class Meta(BaseDeviceCSVForm.Meta):
|
||||||
fields = [
|
fields = [
|
||||||
'name', 'device_role', 'tenant', 'manufacturer', 'model_name', 'platform', 'serial', 'asset_tag', 'status',
|
'name', 'device_role', 'tenant', 'manufacturer', 'model_name', 'platform', 'serial', 'asset_tag', 'status',
|
||||||
'site', 'rack_name', 'position', 'face',
|
'site', 'rack_name', 'position', 'face',
|
||||||
@ -724,7 +783,7 @@ class DeviceFromCSVForm(BaseDeviceFromCSVForm):
|
|||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
|
||||||
super(DeviceFromCSVForm, self).clean()
|
super(DeviceCSVForm, self).clean()
|
||||||
|
|
||||||
site = self.cleaned_data.get('site')
|
site = self.cleaned_data.get('site')
|
||||||
rack_name = self.cleaned_data.get('rack_name')
|
rack_name = self.cleaned_data.get('rack_name')
|
||||||
@ -749,18 +808,20 @@ class DeviceFromCSVForm(BaseDeviceFromCSVForm):
|
|||||||
raise forms.ValidationError('Invalid rack face ({}); must be "front" or "rear".'.format(face))
|
raise forms.ValidationError('Invalid rack face ({}); must be "front" or "rear".'.format(face))
|
||||||
|
|
||||||
|
|
||||||
class ChildDeviceFromCSVForm(BaseDeviceFromCSVForm):
|
class ChildDeviceCSVForm(BaseDeviceCSVForm):
|
||||||
parent = FlexibleModelChoiceField(
|
parent = FlexibleModelChoiceField(
|
||||||
queryset=Device.objects.all(),
|
queryset=Device.objects.all(),
|
||||||
to_field_name='name',
|
to_field_name='name',
|
||||||
required=False,
|
help_text='Name of parent device',
|
||||||
error_messages={
|
error_messages={
|
||||||
'invalid_choice': 'Parent device not found.'
|
'invalid_choice': 'Parent device not found.',
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
device_bay_name = forms.CharField(required=False)
|
device_bay_name = forms.CharField(
|
||||||
|
help_text='Name of device bay',
|
||||||
|
)
|
||||||
|
|
||||||
class Meta(BaseDeviceFromCSVForm.Meta):
|
class Meta(BaseDeviceCSVForm.Meta):
|
||||||
fields = [
|
fields = [
|
||||||
'name', 'device_role', 'tenant', 'manufacturer', 'model_name', 'platform', 'serial', 'asset_tag', 'status',
|
'name', 'device_role', 'tenant', 'manufacturer', 'model_name', 'platform', 'serial', 'asset_tag', 'status',
|
||||||
'parent', 'device_bay_name',
|
'parent', 'device_bay_name',
|
||||||
@ -768,7 +829,7 @@ class ChildDeviceFromCSVForm(BaseDeviceFromCSVForm):
|
|||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
|
||||||
super(ChildDeviceFromCSVForm, self).clean()
|
super(ChildDeviceCSVForm, self).clean()
|
||||||
|
|
||||||
parent = self.cleaned_data.get('parent')
|
parent = self.cleaned_data.get('parent')
|
||||||
device_bay_name = self.cleaned_data.get('device_bay_name')
|
device_bay_name = self.cleaned_data.get('device_bay_name')
|
||||||
@ -778,20 +839,15 @@ class ChildDeviceFromCSVForm(BaseDeviceFromCSVForm):
|
|||||||
try:
|
try:
|
||||||
device_bay = DeviceBay.objects.get(device=parent, name=device_bay_name)
|
device_bay = DeviceBay.objects.get(device=parent, name=device_bay_name)
|
||||||
if device_bay.installed_device:
|
if device_bay.installed_device:
|
||||||
self.add_error('device_bay_name',
|
self.add_error(
|
||||||
"Device bay ({} {}) is already occupied".format(parent, device_bay_name))
|
'device_bay_name', "Device bay ({} {}) is already occupied".format(parent, device_bay_name)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.instance.parent_bay = device_bay
|
self.instance.parent_bay = device_bay
|
||||||
except DeviceBay.DoesNotExist:
|
except DeviceBay.DoesNotExist:
|
||||||
self.add_error('device_bay_name', "Parent device/bay ({} {}) not found".format(parent, device_bay_name))
|
self.add_error(
|
||||||
|
'device_bay_name', "Parent device/bay ({} {}) not found".format(parent, device_bay_name)
|
||||||
|
)
|
||||||
class DeviceImportForm(BootstrapMixin, BulkImportForm):
|
|
||||||
csv = CSVDataField(csv_form=DeviceFromCSVForm)
|
|
||||||
|
|
||||||
|
|
||||||
class ChildDeviceImportForm(BootstrapMixin, BulkImportForm):
|
|
||||||
csv = CSVDataField(csv_form=ChildDeviceFromCSVForm)
|
|
||||||
|
|
||||||
|
|
||||||
class DeviceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
class DeviceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
||||||
|
@ -23,14 +23,14 @@ from extras.models import Graph, TopologyMap, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_S
|
|||||||
from utilities.forms import ConfirmationForm
|
from utilities.forms import ConfirmationForm
|
||||||
from utilities.paginator import EnhancedPaginator
|
from utilities.paginator import EnhancedPaginator
|
||||||
from utilities.views import (
|
from utilities.views import (
|
||||||
BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
|
BulkDeleteView, BulkEditView, BulkImportView, BulkImportView2, ObjectDeleteView, ObjectEditView, ObjectListView,
|
||||||
)
|
)
|
||||||
from . import filters, forms, tables
|
from . import filters, forms, tables
|
||||||
from .models import (
|
from .models import (
|
||||||
CONNECTION_STATUS_CONNECTED, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device,
|
CONNECTION_STATUS_CONNECTED, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device,
|
||||||
DeviceBay, DeviceBayTemplate, DeviceRole, DeviceType, Interface, InterfaceConnection, InterfaceTemplate,
|
DeviceBay, DeviceBayTemplate, DeviceRole, DeviceType, Interface, InterfaceConnection, InterfaceTemplate,
|
||||||
Manufacturer, InventoryItem, Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack, RackGroup,
|
Manufacturer, InventoryItem, Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack,
|
||||||
RackReservation, RackRole, Region, Site,
|
RackGroup, RackReservation, RackRole, Region, Site,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -217,11 +217,10 @@ class SiteDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
|||||||
default_return_url = 'dcim:site_list'
|
default_return_url = 'dcim:site_list'
|
||||||
|
|
||||||
|
|
||||||
class SiteBulkImportView(PermissionRequiredMixin, BulkImportView):
|
class SiteBulkImportView(PermissionRequiredMixin, BulkImportView2):
|
||||||
permission_required = 'dcim.add_site'
|
permission_required = 'dcim.add_site'
|
||||||
form = forms.SiteImportForm
|
model_form = forms.SiteCSVForm
|
||||||
table = tables.SiteTable
|
table = tables.SiteTable
|
||||||
template_name = 'dcim/site_import.html'
|
|
||||||
default_return_url = 'dcim:site_list'
|
default_return_url = 'dcim:site_list'
|
||||||
|
|
||||||
|
|
||||||
@ -388,11 +387,10 @@ class RackDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
|||||||
default_return_url = 'dcim:rack_list'
|
default_return_url = 'dcim:rack_list'
|
||||||
|
|
||||||
|
|
||||||
class RackBulkImportView(PermissionRequiredMixin, BulkImportView):
|
class RackBulkImportView(PermissionRequiredMixin, BulkImportView2):
|
||||||
permission_required = 'dcim.add_rack'
|
permission_required = 'dcim.add_rack'
|
||||||
form = forms.RackImportForm
|
model_form = forms.RackCSVForm
|
||||||
table = tables.RackImportTable
|
table = tables.RackImportTable
|
||||||
template_name = 'dcim/rack_import.html'
|
|
||||||
default_return_url = 'dcim:rack_list'
|
default_return_url = 'dcim:rack_list'
|
||||||
|
|
||||||
|
|
||||||
@ -864,17 +862,17 @@ class DeviceDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
|||||||
default_return_url = 'dcim:device_list'
|
default_return_url = 'dcim:device_list'
|
||||||
|
|
||||||
|
|
||||||
class DeviceBulkImportView(PermissionRequiredMixin, BulkImportView):
|
class DeviceBulkImportView(PermissionRequiredMixin, BulkImportView2):
|
||||||
permission_required = 'dcim.add_device'
|
permission_required = 'dcim.add_device'
|
||||||
form = forms.DeviceImportForm
|
model_form = forms.DeviceCSVForm
|
||||||
table = tables.DeviceImportTable
|
table = tables.DeviceImportTable
|
||||||
template_name = 'dcim/device_import.html'
|
template_name = 'dcim/device_import.html'
|
||||||
default_return_url = 'dcim:device_list'
|
default_return_url = 'dcim:device_list'
|
||||||
|
|
||||||
|
|
||||||
class ChildDeviceBulkImportView(PermissionRequiredMixin, BulkImportView):
|
class ChildDeviceBulkImportView(PermissionRequiredMixin, BulkImportView2):
|
||||||
permission_required = 'dcim.add_device'
|
permission_required = 'dcim.add_device'
|
||||||
form = forms.ChildDeviceImportForm
|
model_form = forms.ChildDeviceCSVForm
|
||||||
table = tables.DeviceImportTable
|
table = tables.DeviceImportTable
|
||||||
template_name = 'dcim/device_import_child.html'
|
template_name = 'dcim/device_import_child.html'
|
||||||
default_return_url = 'dcim:device_list'
|
default_return_url = 'dcim:device_list'
|
||||||
|
@ -1,103 +1,5 @@
|
|||||||
{% extends '_base.html' %}
|
{% extends 'utilities/obj_import.html' %}
|
||||||
{% load form_helpers %}
|
|
||||||
|
|
||||||
{% block title %}Device Import{% endblock %}
|
{% block tabs %}
|
||||||
|
{% include 'dcim/inc/device_import_header.html' %}
|
||||||
{% block content %}
|
|
||||||
{% include 'dcim/inc/device_import_header.html' %}
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-12">
|
|
||||||
<form action="." method="post" class="form">
|
|
||||||
{% csrf_token %}
|
|
||||||
{% render_form form %}
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="col-md-12 text-right">
|
|
||||||
<button type="submit" class="btn btn-primary">Submit</button>
|
|
||||||
{% if return_url %}
|
|
||||||
<a href="{% url return_url %}" class="btn btn-default">Cancel</a>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<h4>CSV Format</h4>
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Field</th>
|
|
||||||
<th>Description</th>
|
|
||||||
<th>Example</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>Name</td>
|
|
||||||
<td>Device name (optional)</td>
|
|
||||||
<td>rack101_sw1</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Device role</td>
|
|
||||||
<td>Functional role of device</td>
|
|
||||||
<td>ToR Switch</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Tenant</td>
|
|
||||||
<td>Name of tenant (optional)</td>
|
|
||||||
<td>Pied Piper</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Device manufacturer</td>
|
|
||||||
<td>Hardware manufacturer</td>
|
|
||||||
<td>Juniper</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Device model</td>
|
|
||||||
<td>Hardware model</td>
|
|
||||||
<td>EX4300-48T</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Platform</td>
|
|
||||||
<td>Software running on device (optional)</td>
|
|
||||||
<td>Juniper Junos</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Serial number</td>
|
|
||||||
<td>Physical serial number (optional)</td>
|
|
||||||
<td>CAB00577291</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Asset tag</td>
|
|
||||||
<td>Unique alphanumeric tag (optional)</td>
|
|
||||||
<td>ABC123456</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Status</td>
|
|
||||||
<td>Current status</td>
|
|
||||||
<td>Active</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Site</td>
|
|
||||||
<td>Site name</td>
|
|
||||||
<td>Ashburn-VA</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Rack</td>
|
|
||||||
<td>Rack name (optional)</td>
|
|
||||||
<td>R101</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Position (U)</td>
|
|
||||||
<td>Lowest-numbered rack unit occupied by the device (optional)</td>
|
|
||||||
<td>21</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Face</td>
|
|
||||||
<td>Rack face; front or rear (required if position is set)</td>
|
|
||||||
<td>Rear</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<h4>Example</h4>
|
|
||||||
<pre>rack101_sw1,ToR Switch,Pied Piper,Juniper,EX4300-48T,Juniper Junos,CAB00577291,ABC123456,Active,Ashburn-VA,R101,21,Rear</pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1,93 +1,5 @@
|
|||||||
{% extends '_base.html' %}
|
{% extends 'utilities/obj_import.html' %}
|
||||||
{% load form_helpers %}
|
|
||||||
|
|
||||||
{% block title %}Device Import{% endblock %}
|
{% block tabs %}
|
||||||
|
{% include 'dcim/inc/device_import_header.html' with active_tab='child_import' %}
|
||||||
{% block content %}
|
|
||||||
{% include 'dcim/inc/device_import_header.html' with active_tab='child_import' %}
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-12">
|
|
||||||
<form action="." method="post" class="form">
|
|
||||||
{% csrf_token %}
|
|
||||||
{% render_form form %}
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="col-md-12 text-right">
|
|
||||||
<button type="submit" class="btn btn-primary">Submit</button>
|
|
||||||
{% if return_url %}
|
|
||||||
<a href="{% url return_url %}" class="btn btn-default">Cancel</a>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<h4>CSV Format</h4>
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Field</th>
|
|
||||||
<th>Description</th>
|
|
||||||
<th>Example</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>Name</td>
|
|
||||||
<td>Device name (optional)</td>
|
|
||||||
<td>Blade12</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Device role</td>
|
|
||||||
<td>Functional role of device</td>
|
|
||||||
<td>Blade Server</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Tenant</td>
|
|
||||||
<td>Name of tenant (optional)</td>
|
|
||||||
<td>Pied Piper</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Device manufacturer</td>
|
|
||||||
<td>Hardware manufacturer</td>
|
|
||||||
<td>Dell</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Device model</td>
|
|
||||||
<td>Hardware model</td>
|
|
||||||
<td>BS2000T</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Platform</td>
|
|
||||||
<td>Software running on device (optional)</td>
|
|
||||||
<td>Linux</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Serial number</td>
|
|
||||||
<td>Physical serial number (optional)</td>
|
|
||||||
<td>CAB00577291</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Asset tag</td>
|
|
||||||
<td>Unique alphanumeric tag (optional)</td>
|
|
||||||
<td>ABC123456</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Status</td>
|
|
||||||
<td>Current status</td>
|
|
||||||
<td>Active</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Parent device</td>
|
|
||||||
<td>Parent device</td>
|
|
||||||
<td>Server101</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Device bay</td>
|
|
||||||
<td>Device bay name</td>
|
|
||||||
<td>Slot 4</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<h4>Example</h4>
|
|
||||||
<pre>Blade12,Blade Server,Pied Piper,Dell,BS2000T,Linux,CAB00577291,ABC123456,Active,Server101,Slot4</pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
<h1>Device Import</h1>
|
|
||||||
<ul class="nav nav-tabs" style="margin-bottom: 20px">
|
<ul class="nav nav-tabs" style="margin-bottom: 20px">
|
||||||
<li role="presentation"{% if not active_tab %} class="active"{% endif %}><a href="{% url 'dcim:device_import' %}">Racked Devices</a></li>
|
<li role="presentation"{% if not active_tab %} class="active"{% endif %}><a href="{% url 'dcim:device_import' %}">Racked Devices</a></li>
|
||||||
<li role="presentation"{% if active_tab == 'child_import' %} class="active"{% endif %}><a href="{% url 'dcim:device_import_child' %}">Child Devices</a></li>
|
<li role="presentation"{% if active_tab == 'child_import' %} class="active"{% endif %}><a href="{% url 'dcim:device_import_child' %}">Child Devices</a></li>
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
{% extends 'utilities/obj_import.html' %}
|
|
||||||
|
|
||||||
{% block title %}Rack Import{% endblock %}
|
|
||||||
|
|
||||||
{% block instructions %}
|
|
||||||
<h4>CSV Format</h4>
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Field</th>
|
|
||||||
<th>Description</th>
|
|
||||||
<th>Example</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>Site</td>
|
|
||||||
<td>Name of the assigned site</td>
|
|
||||||
<td>DC-4</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Group</td>
|
|
||||||
<td>Rack group name (optional)</td>
|
|
||||||
<td>Cage 1400</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Name</td>
|
|
||||||
<td>Internal rack name</td>
|
|
||||||
<td>R101</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Facility ID</td>
|
|
||||||
<td>Rack ID assigned by the facility (optional)</td>
|
|
||||||
<td>J12.100</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Tenant</td>
|
|
||||||
<td>Name of tenant (optional)</td>
|
|
||||||
<td>Pied Piper</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Role</td>
|
|
||||||
<td>Functional role (optional)</td>
|
|
||||||
<td>Compute</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Type</td>
|
|
||||||
<td>Rack type (optional)</td>
|
|
||||||
<td>4-post cabinet</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Width</td>
|
|
||||||
<td>Rail-to-rail width (19 or 23 inches)</td>
|
|
||||||
<td>19</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Height</td>
|
|
||||||
<td>Height in rack units</td>
|
|
||||||
<td>42</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Descending units</td>
|
|
||||||
<td>Units are numbered top-to-bottom</td>
|
|
||||||
<td>False</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<h4>Example</h4>
|
|
||||||
<pre>DC-4,Cage 1400,R101,J12.100,Pied Piper,Compute,4-post cabinet,19,42,False</pre>
|
|
||||||
{% endblock %}
|
|
@ -1,81 +0,0 @@
|
|||||||
{% extends '_base.html' %}
|
|
||||||
{% load form_helpers %}
|
|
||||||
|
|
||||||
{% block title %}Site Import{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<h1>Site Import</h1>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<form action="." method="post" class="form">
|
|
||||||
{% csrf_token %}
|
|
||||||
{% render_form form %}
|
|
||||||
<div class="form-group">
|
|
||||||
<button type="submit" class="btn btn-primary">Submit</button>
|
|
||||||
<a href="{% url return_url %}" class="btn btn-default">Cancel</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<h4>CSV Format</h4>
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Field</th>
|
|
||||||
<th>Description</th>
|
|
||||||
<th>Example</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>Name</td>
|
|
||||||
<td>Site's proper name</td>
|
|
||||||
<td>ASH-4 South</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Slug</td>
|
|
||||||
<td>URL-friendly name</td>
|
|
||||||
<td>ash4-south</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Region</td>
|
|
||||||
<td>Name of region (optional)</td>
|
|
||||||
<td>North America</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Tenant</td>
|
|
||||||
<td>Name of tenant (optional)</td>
|
|
||||||
<td>Pied Piper</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Facility</td>
|
|
||||||
<td>Name of the hosting facility (optional)</td>
|
|
||||||
<td>Equinix DC6</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>ASN</td>
|
|
||||||
<td>Autonomous system number (optional)</td>
|
|
||||||
<td>65000</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Contact Name</td>
|
|
||||||
<td>Name of administrative contact (optional)</td>
|
|
||||||
<td>Hank Hill</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Contact Phone</td>
|
|
||||||
<td>Phone number (optional)</td>
|
|
||||||
<td>+1-214-555-1234</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Contact E-mail</td>
|
|
||||||
<td>E-mail address (optional)</td>
|
|
||||||
<td>hhill@example.com</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<h4>Example</h4>
|
|
||||||
<pre>ASH-4 South,ash4-south,North America,Pied Piper,Equinix DC6,65000,Hank Hill,+1-214-555-1234,hhill@example.com</pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>{% block title %}{{ obj_type|bettertitle }} Import{% endblock %}</h1>
|
<h1>{% block title %}{{ obj_type|bettertitle }} Import{% endblock %}</h1>
|
||||||
|
{% block tabs %}{% endblock %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
{% if form.non_field_errors %}
|
{% if form.non_field_errors %}
|
||||||
|
Loading…
Reference in New Issue
Block a user