diff --git a/src/rockstor/rest_framework_custom/oauth_wrapper.py b/src/rockstor/rest_framework_custom/oauth_wrapper.py index bb428ca5e..6d8e2d74a 100644 --- a/src/rockstor/rest_framework_custom/oauth_wrapper.py +++ b/src/rockstor/rest_framework_custom/oauth_wrapper.py @@ -22,7 +22,15 @@ class RockstorOAuth2Authentication(OAuth2Authentication): def authenticate(self, request): - user, access_token = super(RockstorOAuth2Authentication, self).authenticate(request) + #on success we get a (user, access_token) tuple. + #if auth is unsuccessful, we get None + #finally, the workaround case is when we get the access_token + #but user is None(due to a bug/feature in oauth2_provider). In + #this case, we set the user and return the tuple. + creds = super(RockstorOAuth2Authentication, self).authenticate(request) + if (creds is None or len(creds) != 2): + return None + user, access_token = creds if (user is None): user = access_token.application.user return user, access_token diff --git a/src/rockstor/smart_manager/replication/listener_broker.py b/src/rockstor/smart_manager/replication/listener_broker.py index 7db5d9a80..23d47ed1b 100644 --- a/src/rockstor/smart_manager/replication/listener_broker.py +++ b/src/rockstor/smart_manager/replication/listener_broker.py @@ -20,8 +20,9 @@ import zmq import os import json +import time from storageadmin.models import (NetworkInterface, Appliance) -from smart_manager.models import (ReplicaTrail, ReplicaShare, Replica) +from smart_manager.models import (ReplicaTrail, ReplicaShare, Replica, Service) from django.conf import settings from sender import Sender from receiver import Receiver @@ -40,6 +41,7 @@ def __init__(self): self.remote_senders = {} # Active incoming/remote Sender/client map. self.MAX_ATTEMPTS = settings.REPLICATION.get('max_send_attempts') self.uuid = self.listener_interface = self.listener_port = None + self.trail_prune_time = None super(ReplicaScheduler, self).__init__() def _prune_workers(self, workers): @@ -157,7 +159,6 @@ def _process_send(self, replica): def run(self): self.law = APIWrapper() try: - from smart_manager.models import Service so = Service.objects.get(name='replication') config_d = json.loads(so.config) self.listener_interface = NetworkInterface.objects.get(name=config_d['network_interface']).ipaddr @@ -281,6 +282,13 @@ def run(self): iterations = 10 self._prune_senders() self._delete_receivers() + cur_time = time.time() + if (self.trail_prune_time is None or (cur_time - self.trail_prune_time) > 3600): + #prune send/receive trails every hour or so. + self.trail_prune_time = cur_time + map(self.prune_replica_trail, Replica.objects.filter()) + map(self.prune_receive_trail, ReplicaShare.objects.filter()) + logger.debug('Replica trails are truncated successfully.') if (os.getppid() != self.ppid): logger.error('Parent exited. Aborting.') diff --git a/src/rockstor/smart_manager/replication/util.py b/src/rockstor/smart_manager/replication/util.py index 5fee66d45..e9cfd3693 100644 --- a/src/rockstor/smart_manager/replication/util.py +++ b/src/rockstor/smart_manager/replication/util.py @@ -93,7 +93,7 @@ def update_receive_trail(self, rtid, data): (url, e.__str__())) raise Exception(msg) - def prune_trail(self, url, days=1): + def prune_trail(self, url, days=7): try: data = {'days': days, } return self.law.api_call(url, data=data, calltype='delete', save_error=False) @@ -101,12 +101,12 @@ def prune_trail(self, url, days=1): msg = ('Exception while pruning trail for url(%s): %s' % (url, e.__str__())) raise Exception(msg) - def prune_receive_trail(self, rid): - url = ('sm/replicas/rtrail/rshare/%d' % rid) + def prune_receive_trail(self, ro): + url = ('sm/replicas/rtrail/rshare/%d' % ro.id) return self.prune_trail(url) - def prune_replica_trail(self, rid): - url = ('sm/replicas/trail/replica/%d' % rid) + def prune_replica_trail(self, ro): + url = ('sm/replicas/trail/replica/%d' % ro.id) return self.prune_trail(url) def create_snapshot(self, sname, snap_name, snap_type='replication'): diff --git a/src/rockstor/storageadmin/static/storageadmin/js/views/replication.js b/src/rockstor/storageadmin/static/storageadmin/js/views/replication.js index bf5692fb0..3280a2808 100644 --- a/src/rockstor/storageadmin/static/storageadmin/js/views/replication.js +++ b/src/rockstor/storageadmin/static/storageadmin/js/views/replication.js @@ -56,6 +56,8 @@ ReplicationView = RockstorLayoutView.extend({ render: function() { this.fetch(this.renderReplicas, this); + RockStorSocket.services = io.connect('/services', {'secure': true, 'force new connection': true}); + RockStorSocket.addListener(this.serviceStatusSync, this, 'services:get_services'); return this; }, @@ -222,7 +224,7 @@ ReplicationView = RockstorLayoutView.extend({ _this.$('#replication-warning').hide(); }, error: function(xhr, status, error) { - _this.setStatusError(_this.serviceName, xhr); + _this.$('input[name="replica-service-checkbox"]').bootstrapSwitch('state', _this.current_status, true); } }); }, @@ -241,7 +243,7 @@ ReplicationView = RockstorLayoutView.extend({ _this.$('#replication-warning').show(); }, error: function(xhr, status, error) { - _this.setStatusError(_this.serviceName, xhr); + _this.$('input[name="replica-service-checkbox"]').bootstrapSwitch('state', _this.current_status, true); } }); }, @@ -255,19 +257,19 @@ ReplicationView = RockstorLayoutView.extend({ } }, - setStatusError: function(serviceName, xhr) { - var statusEl = this.$('div.command-status[data-service-name="' + serviceName + '"]'); - var msg = parseXhrError(xhr); - // remove any existing error popups - $('body').find('#' + serviceName + 'err-popup').remove(); - // add icon and popup - statusEl.empty(); - var icon = $('').addClass('icon-exclamation-sign').attr('rel', '#' + serviceName + '-err-popup'); - statusEl.append(icon); - var errPopup = this.$('#' + serviceName + '-err-popup'); - var errPopupContent = this.$('#' + serviceName + '-err-popup > div'); - errPopupContent.html(msg); - statusEl.click(function(){ errPopup.overlay().load(); }); + serviceStatusSync: function(data) { + if (data.replication.running > 0) { + this.current_status = false; + this.$('#replication-warning').show(); + } else { + this.current_status = true; + this.$('#replication-warning').hide(); + } + this.$('input[name="replica-service-checkbox"]').bootstrapSwitch('state', this.current_status, true); + }, + + cleanup: function() { + RockStorSocket.removeOneListener('services'); } }); diff --git a/src/rockstor/storageadmin/views/network.py b/src/rockstor/storageadmin/views/network.py index 9c571cce2..686f9d0a9 100644 --- a/src/rockstor/storageadmin/views/network.py +++ b/src/rockstor/storageadmin/views/network.py @@ -155,7 +155,7 @@ def _validate_netmask(self, request): bits = int(netmask) except ValueError: #assume ip address format was provided - bits = sum([bin(int(x)).count('1') for x in '255.255.255'.split('.')]) + bits = sum([bin(int(x)).count('1') for x in netmask.split('.')]) if (bits < 1 or bits > 32): e_msg = ('Provided netmask value(%s) is invalid. Number of ' 'bits in netmask must be between 1-32' % netmask) diff --git a/src/rockstor/system/osi.py b/src/rockstor/system/osi.py index ffe178251..56b8cf571 100644 --- a/src/rockstor/system/osi.py +++ b/src/rockstor/system/osi.py @@ -207,16 +207,14 @@ def hostid(): def config_network_device(name, dtype='ethernet', method='auto', ipaddr=None, netmask=None, autoconnect='yes', gateway=None, dns_servers=None): - #1. delete the existing connection - show_cmd = [NMCLI, 'c', 'show', name] - o, e, rc = run_command(show_cmd, throw=False) - if (rc == 0): - run_command([NMCLI, 'c', 'delete', name]) - elif (rc != 0 and rc != 10): - #unknown error - e_msg = ('Unexpected error while running command: %s. out: %s err: ' - '%s' % (show_cmd, o, e)) - raise Exception(e_msg) + #1. delete any existing connections that are using the given device. + show_cmd = [NMCLI, 'c', 'show'] + o, e, rc = run_command(show_cmd) + for l in o: + fields = l.strip().split() + if (len(fields) > 3 and fields[-1] == name): + #fields[-3] is the uuid of the connection + run_command([NMCLI, 'c', 'delete', fields[-3]]) #2. Add a new connection add_cmd = [NMCLI, 'c', 'add', 'type', dtype, 'con-name', name, 'ifname', name] if (method == 'manual'):