Skip to content

Commit

Permalink
Merge pull request #2807 from freenas/FIX-83708
Browse files Browse the repository at this point in the history
tkt-83708: Fibre Channel Ports to middlewared
  • Loading branch information
themylogin committed Mar 27, 2019
2 parents 8746436 + 2a70a8c commit 05b3ff7
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 182 deletions.
101 changes: 5 additions & 96 deletions gui/api/resources.py
Expand Up @@ -29,10 +29,7 @@
import json
import logging
import os
import re
import subprocess
import urllib.parse
import sysctl

from collections import OrderedDict
from croniter import croniter
Expand Down Expand Up @@ -85,7 +82,7 @@
from freenasUI.services.forms import iSCSITargetPortalIPForm
from freenasUI.services.models import (
iSCSITargetGlobalConfiguration,
iSCSITargetPortal, iSCSITargetPortalIP, FibreChannelToTarget
iSCSITargetPortal, iSCSITargetPortalIP,
)
from freenasUI.sharing.models import NFS_Share, NFS_Share_Path
from freenasUI.sharing.forms import NFS_SharePathForm
Expand Down Expand Up @@ -3885,99 +3882,11 @@ class Meta:
max_limit = 0

def get_list(self, request, **kwargs):
from lxml import etree

_n = notifier()
node = None
if not _n.is_freenas() and _n.failover_licensed():
node = _n.failover_node()

fcportmap = {}
for fbtt in FibreChannelToTarget.objects.all():
fcportmap[fbtt.fc_port] = fbtt.fc_target

proc = subprocess.Popen([
"/usr/sbin/ctladm",
"portlist",
"-x",
], stdout=subprocess.PIPE, encoding='utf8')
data = proc.communicate()[0]
doc = etree.fromstring(data)
results = []
for e in doc.xpath("//frontend_type[text()='camtgt']"):
tag_port = e.getparent()
name = tag_port.xpath('./port_name')[0].text
reg = re.search('\d+', name)
if reg:
port = reg.group(0)
else:
port = '0'
vport = tag_port.xpath('./physical_port')[0].text
if vport != '0':
name += '/%s' % vport
state = 'NO_LINK'
speed = None
wwpn = None
if vport == '0':
mibname = port
else:
mibname = '%s.chan%s' % (port, vport)
mib = 'dev.isp.%s.loopstate' % mibname
loopstate = sysctl.filter(mib)
if loopstate:
loopstate = loopstate[0].value
if loopstate > 0 and loopstate < 10:
state = 'SCANNING'
elif loopstate == 10:
state = 'READY'
if loopstate > 0:
speedres = sysctl.filter('dev.isp.%s.speed' % mibname)
if speedres:
speed = speedres[0].value
mib = 'dev.isp.%s.wwpn' % mibname
_filter = sysctl.filter(mib)
if _filter:
wwpn = 'naa.%x' % _filter[0].value
if name in fcportmap:
targetobj = fcportmap[name]
if targetobj is not None:
mode = 'TARGET'
target = fcportmap[name].id
else:
mode = 'INITIATOR'
target = None
else:
mode = 'DISABLED'
target = None
initiators = []
for i in tag_port.xpath('./initiator'):
initiators.append(i.text)

if node:
for e in doc.xpath("//frontend_type[text()='ha']"):
parent = e.getparent()
port_name = parent.xpath('./port_name')[0].text
if ':' in port_name:
port_name = port_name.split(':', 1)[1]
physical_port = parent.xpath('./physical_port')[0].text
if physical_port != '0':
port_name += '/%s' % physical_port
if port_name != name:
continue
for i in parent.xpath('./initiator'):
initiators.append("%s (Node %s)" % (i.text, ('B' if node == 'A' else 'A')))

results.append(FCPort(
port=port,
vport=vport,
name=name,
wwpn=wwpn,
mode=mode,
target=target,
state=state,
speed=speed,
initiators=initiators,
))
with client as c:
for port in c.call("fcport.query"):
port.pop("id")
results.append(FCPort(**port))

limit = self._meta.limit
if 'HTTP_X_RANGE' in request.META:
Expand Down
100 changes: 14 additions & 86 deletions gui/services/views.py
Expand Up @@ -25,7 +25,6 @@
#####################################################################
import json
import logging
import sysctl

from django.core.urlresolvers import reverse
from django.shortcuts import render
Expand All @@ -36,9 +35,9 @@
idmap_tdb,
DS_TYPE_CIFS
)
from freenasUI.directoryservice.views import get_directoryservice_status
from freenasUI.freeadmin.apppool import appPool
from freenasUI.freeadmin.views import JsonResp
from freenasUI.middleware.client import client
from freenasUI.middleware.exceptions import MiddlewareError
from freenasUI.middleware.form import handle_middleware_validation
from freenasUI.middleware.notifier import notifier
Expand All @@ -48,7 +47,6 @@
CIFSForm,
S3Form
)
from freenasUI.system.models import Tunable
from freenasUI.support.utils import fc_enabled
from middlewared.client import ValidationErrors

Expand Down Expand Up @@ -86,9 +84,9 @@ def core(request):
extra_services['asigra'] = asigra.get_edit_url()

try:
cifs = models.CIFS.objects.order_by("-id")[0]
models.CIFS.objects.order_by("-id")[0]
except IndexError:
cifs = models.CIFS.objects.create()
models.CIFS.objects.create()

try:
dynamicdns = models.DynamicDNS.objects.order_by("-id")[0]
Expand Down Expand Up @@ -121,9 +119,9 @@ def core(request):
rsyncd = models.Rsyncd.objects.create()

try:
s3 = models.S3.objects.order_by("-id")[0]
models.S3.objects.order_by("-id")[0]
except IndexError:
s3 = models.S3.objects.create()
models.S3.objects.create()

try:
smart = models.SMART.objects.order_by("-id")[0]
Expand Down Expand Up @@ -253,8 +251,6 @@ def services_cifs(request):
def fibrechanneltotarget(request):

i = 0
sysctl_set = {}
loader = False
while True:

fc_port = request.POST.get('fcport-%d-port' % i)
Expand All @@ -263,88 +259,20 @@ def fibrechanneltotarget(request):
if fc_port is None:
break

port = fc_port.replace('isp', '').replace('/', ',')
if ',' in port:
port_number, vport = port.split(',', 1)
mibname = '%s.chan%s' % (port_number, vport)
else:
port_number = port
vport = None
mibname = port

role = sysctl.filter('dev.isp.%s.role' % mibname)
if role:
role = role[0]
tun_var = 'hint.isp.%s.role' % mibname

qs = models.FibreChannelToTarget.objects.filter(fc_port=fc_port)
if qs.exists():
fctt = qs[0]
else:
fctt = models.FibreChannelToTarget()
fctt.fc_port = fc_port
# Initiator mode
if fc_target in ('false', False):
if role:
# From disabled to initiator, just set sysctl
if role.value == 0:
role.value = 2
# From target to initiator, reload ctld then set to 2
elif role.value == 1:
sysctl_set[mibname] = 2
fctt.fc_target = None
fctt.save()
qs = Tunable.objects.filter(tun_var=tun_var)
if qs.exists():
tun = qs[0]
if tun.tun_value != '2':
tun.tun_value = '2'
loader = True
tun.save()
else:
tun = Tunable()
tun.tun_var = tun_var
tun.tun_value = '2'
tun.save()
loader = True
# Disabled
mode = 'INITIATOR'
fc_target = None
elif fc_target is None:
if role:
# From initiator to disabled, just set sysctl
if role.value == 2:
role.value = 0
if fctt.id:
fctt.delete()
qs = Tunable.objects.filter(tun_var=tun_var)
if qs.exists():
loader = True
qs.delete()
# Target mode
mode = 'DISABLED'
fc_target = None
else:
if role:
# From initiator to target, first set sysctl
if role.value == 2:
role.value = 0
fctt.fc_target = models.iSCSITarget.objects.get(id=fc_target)
fctt.save()
qs = Tunable.objects.filter(tun_var=tun_var)
if qs.exists():
loader = True
qs.delete()
mode = 'TARGET'
fc_target = int(fc_target)

i += 1
with client as c:
c.call("fcport.update", fc_port, {"mode": mode, "target": fc_target})

if i > 0:
notifier().reload("iscsitarget")

for mibname, val in list(sysctl_set.items()):
role = sysctl.filter('dev.isp.%s.role' % mibname)
if role:
role = role[0]
role.value = val

if loader:
notifier().reload('loader')
i += 1

return JsonResp(
request,
Expand Down

0 comments on commit 05b3ff7

Please sign in to comment.