diff --git a/src/ralph/cmdb/api.py b/src/ralph/cmdb/api.py index e643b283a2..8411e8d6fd 100644 --- a/src/ralph/cmdb/api.py +++ b/src/ralph/cmdb/api.py @@ -17,7 +17,6 @@ from ralph.cmdb.monkey import method_check import tastypie from tastypie.resources import Resource -Resource.method_check = method_check from django.conf import settings from django.contrib.auth.models import User @@ -51,6 +50,7 @@ from ralph.cmdb.models_ci import CIOwner, CIOwnershipType from ralph.cmdb.util import breadth_first_search_ci, can_change_ci_state +Resource.method_check = method_check THROTTLE_AT = settings.API_THROTTLING['throttle_at'] TIMEFRAME = settings.API_THROTTLING['timeframe'] diff --git a/src/ralph/cmdb/importer.py b/src/ralph/cmdb/importer.py index 37bd1e403d..fdaf083f93 100644 --- a/src/ralph/cmdb/importer.py +++ b/src/ralph/cmdb/importer.py @@ -42,10 +42,8 @@ from __future__ import unicode_literals import os -os.environ['DJANGO_SETTINGS_MODULE'] = "ralph.settings" import logging -logger = logging.getLogger(__name__) from django.contrib.contenttypes.models import ContentType @@ -57,6 +55,10 @@ from lck.django.common import nested_commit_on_success +os.environ['DJANGO_SETTINGS_MODULE'] = "ralph.settings" +logger = logging.getLogger(__name__) + + def get_layers_for_ci_type(ci_type_id): try: ci_type = cdb.CIType.objects.get(pk=ci_type_id) diff --git a/src/ralph/cmdb/integration/lib/jira.py b/src/ralph/cmdb/integration/lib/jira.py index 474ec37fcd..a91dfed1e0 100644 --- a/src/ralph/cmdb/integration/lib/jira.py +++ b/src/ralph/cmdb/integration/lib/jira.py @@ -6,11 +6,13 @@ from django.utils import simplejson as json import logging -logger = logging.getLogger(__name__) from ralph.cmdb.integration.exceptions import IssueTrackerException +logger = logging.getLogger(__name__) + + class Jira(object): def __init__(self): diff --git a/src/ralph/discovery/models_device.py b/src/ralph/discovery/models_device.py index 73c824ed26..747265e428 100644 --- a/src/ralph/discovery/models_device.py +++ b/src/ralph/discovery/models_device.py @@ -925,6 +925,30 @@ def save(self, sync_fields=True, *args, **kwargs): # the reason (for more, see the source code of SavePrioritized). return super(Device, self).save(*args, **kwargs) + def set_property(self, symbol, value, user): + from ralph.business.models import RoleProperty, RolePropertyValue + try: + p = self.venture_role.roleproperty_set.get(symbol=symbol) + except RoleProperty.DoesNotExist: + p = self.venture.roleproperty_set.get(symbol=symbol) + if value != p.default and not {value, p.default} == {None, ''}: + pv, created = RolePropertyValue.concurrent_get_or_create( + property=p, + device=self, + ) + pv.value = value + pv.save(user=user) + else: + try: + pv = RolePropertyValue.objects.get( + property=p, + device=self, + ) + except RolePropertyValue.DoesNotExist: + pass + else: + pv.delete() + def get_asset(self): asset = None if self.id and 'ralph_assets' in settings.INSTALLED_APPS: diff --git a/src/ralph/discovery/tests/test_models.py b/src/ralph/discovery/tests/test_models.py index 67ab324a46..b89bfc6be2 100644 --- a/src/ralph/discovery/tests/test_models.py +++ b/src/ralph/discovery/tests/test_models.py @@ -19,8 +19,12 @@ from ralph.discovery.tests.util import DeviceFactory, IPAddressFactory from ralph.discovery.models import DeviceType, Device, UptimeSupport from ralph.discovery.models_history import HistoryChange +from ralph.ui.tests.global_utils import UserFactory from ralph.util.models import fields_synced_signal, ChangeTuple -from ralph.util.tests.utils import UserFactory +from ralph.util.tests.utils import ( + UserFactory, RolePropertyTypeFactory, RolePropertyFactory, + VentureRoleFactory, +) from ralph_assets.models import Orientation from ralph_assets.tests.utils.assets import DCAssetFactory, DeviceInfoFactory @@ -184,3 +188,27 @@ def test_orientation_property(self): self.assertEqual(dev_2.orientation, 'middle') with self.assertRaises(AttributeError): dev_2.orientation = Orientation.back.id + + +class DevicePropertiesTest(TestCase): + + def setUp(self): + sample_role = VentureRoleFactory() + RolePropertyFactory( + symbol='my_custom_property_1', + type=RolePropertyTypeFactory(symbol='STRING'), + role=sample_role, + ) + self.sample_device = DeviceFactory( + venture=sample_role.venture, venture_role=sample_role) + self.sample_user = UserFactory() + + def test_successful_save(self): + self.sample_device.set_property( + symbol='my_custom_property_1', value='Test 123', + user=self.sample_user, + ) + self.assertEqual( + self.sample_device.get_property_set(), + {'my_custom_property_1': 'Test 123'} + ) diff --git a/src/ralph/ui/views/common.py b/src/ralph/ui/views/common.py index c91eb9eba1..15997641f5 100644 --- a/src/ralph/ui/views/common.py +++ b/src/ralph/ui/views/common.py @@ -55,8 +55,6 @@ from ralph.scan.models import ScanSummary from ralph.scan.util import get_pending_changes, update_scan_summary from ralph.business.models import ( - RoleProperty, - RolePropertyValue, Venture, VentureRole, ) @@ -659,27 +657,7 @@ def get(self, *args, **kwargs): def save_properties(self, device, properties): for symbol, value in properties.iteritems(): - try: - p = device.venture_role.roleproperty_set.get(symbol=symbol) - except RoleProperty.DoesNotExist: - p = device.venture.roleproperty_set.get(symbol=symbol) - if value != p.default and not {value, p.default} == {None, ''}: - pv, created = RolePropertyValue.concurrent_get_or_create( - property=p, - device=device, - ) - pv.value = value - pv.save(user=self.request.user) - else: - try: - pv = RolePropertyValue.objects.get( - property=p, - device=device, - ) - except RolePropertyValue.DoesNotExist: - pass - else: - pv.delete() + device.set_property(symbol, value, self.request.user) def get_property_form(self, data=None): if not self.object.venture_role: diff --git a/src/ralph/ui/views/racks.py b/src/ralph/ui/views/racks.py index 97041d9c7e..c75af7cbe1 100644 --- a/src/ralph/ui/views/racks.py +++ b/src/ralph/ui/views/racks.py @@ -201,11 +201,15 @@ def sort_tree(self, query, sort): depth, item = top.pop() c = children[item] if sort in ('-position', 'position'): - key = lambda x: (x.get_position() or '').rjust(100) + def key(x): + return (x.get_position() or '').rjust(100) c.sort(key=key, reverse=not sort.startswith('-')) elif sort == '': - key = lambda x: (x.model.type if x.model else None, - (x.get_position() or '').rjust(100)) + def key(x): + return ( + x.model.type if x.model else None, + (x.get_position() or '').rjust(100) + ) c.sort(key=key, reverse=True) top.extend((depth + 1, i) for i in c) item.depth = depth diff --git a/src/ralph/util/models.py b/src/ralph/util/models.py index 66d913daf9..9789127a32 100644 --- a/src/ralph/util/models.py +++ b/src/ralph/util/models.py @@ -18,6 +18,7 @@ from ralph.settings import SYNC_FIELD_MIXIN_NOTIFICATIONS_WHITELIST +from django.contrib.auth.tests import models as auth_test_models ChangeTuple = namedtuple('ChangeTuple', ['field', 'old_value', 'new_value']) @@ -34,7 +35,6 @@ def create_api_key_ignore_dberrors(*args, **kwargs): # workaround for a unit test bug in Django 1.4.x -from django.contrib.auth.tests import models as auth_test_models del auth_test_models.ProfileTestCase.test_site_profile_not_available # signal used by SyncFieldMixin for sending notifications on changed fields diff --git a/src/ralph/util/tests/utils.py b/src/ralph/util/tests/utils.py index 85d5f759c5..9a34260a5a 100644 --- a/src/ralph/util/tests/utils.py +++ b/src/ralph/util/tests/utils.py @@ -10,7 +10,9 @@ from factory.django import DjangoModelFactory from ralph.account.models import Region -from ralph.business.models import Venture, VentureRole +from ralph.business.models import ( + Venture, VentureRole, RolePropertyType, RoleProperty, +) from ralph.cmdb import models_ci from ralph.cmdb.tests.utils import CIFactory from ralph.ui.tests.global_utils import UserFactory @@ -95,3 +97,14 @@ class VentureRoleFactory(DjangoModelFactory): FACTORY_FOR = VentureRole name = factory.Sequence(lambda n: 'Venture role #{}'.format(n)) venture = factory.SubFactory(VentureFactory) + + +class RolePropertyTypeFactory(DjangoModelFactory): + FACTORY_FOR = RolePropertyType + symbol = factory.Sequence(lambda n: 'property_type_{}'.format(n)) + + +class RolePropertyFactory(DjangoModelFactory): + FACTORY_FOR = RoleProperty + symbol = factory.Sequence(lambda n: 'property_{}'.format(n)) + type = factory.SubFactory(RolePropertyTypeFactory)