[SEBA-351] Adding bandwidth profiles to the Subscriber and setting up a default one

Change-Id: Ib4c66652e5b6da24e08509805cd189bb090375d7
diff --git a/Dockerfile.synchronizer b/Dockerfile.synchronizer
index 0da2edb..c94b355 100644
--- a/Dockerfile.synchronizer
+++ b/Dockerfile.synchronizer
@@ -17,7 +17,7 @@
 
 # xosproject/rcord-synchronizer
 
-FROM xosproject/xos-synchronizer-base:2.2.18
+FROM xosproject/xos-synchronizer-base:3.0.0
 
 COPY xos/synchronizer /opt/xos/synchronizers/rcord
 COPY VERSION /opt/xos/synchronizers/rcord/
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..94efe35
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,22 @@
+REGISTRY          ?=
+REPOSITORY        ?=
+DOCKER_BUILD_ARGS ?=
+SERVICE           ?= rcord
+MAKEFILE_DIR      := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+TAG               ?= $(shell cat ${MAKEFILE_DIR}/VERSION)
+IMAGENAME         := ${REGISTRY}${REPOSITORY}${SERVICE}-synchronizer:${TAG}
+SHELL             := /bin/bash
+
+all: build push
+
+build:
+	docker build $(DOCKER_BUILD_ARGS) -t ${IMAGENAME} -f Dockerfile.synchronizer .
+
+push:
+	docker push ${IMAGENAME}
+
+test:
+	source ../../xos/venv-xos/bin/activate && cd xos && nose2 --verbose --coverage-report term || echo "Please install the XOS virtual environment"
+
+migrate:
+	source ../../xos/venv-xos/bin/activate && cd xos && xos-migrate -s $(SERVICE)
\ No newline at end of file
diff --git a/VERSION b/VERSION
index 9084fa2..0c64b5c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.1.0
+1.2.0-dev
diff --git a/xos/synchronizer/migrations/0004_bandwidth_profiles.py b/xos/synchronizer/migrations/0004_bandwidth_profiles.py
new file mode 100644
index 0000000..e3ee1d5
--- /dev/null
+++ b/xos/synchronizer/migrations/0004_bandwidth_profiles.py
@@ -0,0 +1,90 @@
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.11 on 2019-03-15 20:25
+from __future__ import unicode_literals
+
+import core.models.xosbase_header
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('rcord', '0003_auto_20190308_1437'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='BandwidthProfile_decl',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('created', models.DateTimeField(auto_now_add=True, help_text=b'Time this model was created')),
+                ('updated', models.DateTimeField(default=django.utils.timezone.now, help_text=b'Time this model was changed by a non-synchronizer')),
+                ('enacted', models.DateTimeField(blank=True, default=None, help_text=b'When synced, set to the timestamp of the data that was synced', null=True)),
+                ('policed', models.DateTimeField(blank=True, default=None, help_text=b'When policed, set to the timestamp of the data that was policed', null=True)),
+                ('backend_register', models.CharField(blank=True, default=b'{}', max_length=1024, null=True)),
+                ('backend_need_delete', models.BooleanField(default=False)),
+                ('backend_need_reap', models.BooleanField(default=False)),
+                ('backend_status', models.CharField(default=b'Provisioning in progress', max_length=1024)),
+                ('backend_code', models.IntegerField(default=0)),
+                ('deleted', models.BooleanField(default=False)),
+                ('write_protect', models.BooleanField(default=False)),
+                ('lazy_blocked', models.BooleanField(default=False)),
+                ('no_sync', models.BooleanField(default=False)),
+                ('no_policy', models.BooleanField(default=False)),
+                ('policy_status', models.CharField(blank=True, default=b'Policy in process', max_length=1024, null=True)),
+                ('policy_code', models.IntegerField(blank=True, default=0, null=True)),
+                ('leaf_model_name', models.CharField(help_text=b'The most specialized model in this chain of inheritance, often defined by a service developer', max_length=1024)),
+                ('backend_need_delete_policy', models.BooleanField(default=False, help_text=b'True if delete model_policy must be run before object can be reaped')),
+                ('xos_managed', models.BooleanField(default=True, help_text=b'True if xos is responsible for creating/deleting this object')),
+                ('backend_handle', models.CharField(blank=True, help_text=b'Handle used by the backend to track this object', max_length=1024, null=True)),
+                ('changed_by_step', models.DateTimeField(blank=True, default=None, help_text=b'Time this model was changed by a sync step', null=True)),
+                ('changed_by_policy', models.DateTimeField(blank=True, default=None, help_text=b'Time this model was changed by a model policy', null=True)),
+                ('name', models.TextField()),
+                ('cir', models.IntegerField()),
+                ('cbs', models.IntegerField()),
+                ('eir', models.IntegerField()),
+                ('ebs', models.IntegerField()),
+                ('air', models.IntegerField()),
+            ],
+            options={
+                'verbose_name': 'Bandwidth Profile',
+            },
+            bases=(models.Model, core.models.xosbase_header.PlModelMixIn),
+        ),
+        migrations.CreateModel(
+            name='BandwidthProfile',
+            fields=[
+            ],
+            options={
+                'proxy': True,
+                'indexes': [],
+            },
+            bases=('rcord.bandwidthprofile_decl',),
+        ),
+        migrations.AddField(
+            model_name='rcordsubscriber_decl',
+            name='downstream_bps',
+            field=models.ForeignKey(blank=True, help_text=b'The subscriber the IP address belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ds_subscriber', to='rcord.BandwidthProfile_decl'),
+        ),
+        migrations.AddField(
+            model_name='rcordsubscriber_decl',
+            name='upstream_bps',
+            field=models.ForeignKey(blank=True, help_text=b'The subscriber the IP address belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='us_subscriber', to='rcord.BandwidthProfile_decl'),
+        ),
+    ]
diff --git a/xos/synchronizer/migrations/0005_migrate_bandwidth_profiles.py b/xos/synchronizer/migrations/0005_migrate_bandwidth_profiles.py
new file mode 100644
index 0000000..0b9df0f
--- /dev/null
+++ b/xos/synchronizer/migrations/0005_migrate_bandwidth_profiles.py
@@ -0,0 +1,54 @@
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.11 on 2019-03-14 22:35
+from __future__ import unicode_literals
+
+import core.models.xosbase_header
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    def forwards(apps, schema_editor):
+        # create a default bandwidth profile
+        Model = apps.get_model('rcord', 'BandwidthProfile')
+        bp = Model(
+            name="default",
+            cir=10000,
+            cbs=10000,
+            eir=10000,
+            ebs=10000,
+            air=10000,
+        )
+        bp.save()
+
+        # assign the default bandwidth profile to all subscribers
+        subscribers = apps.get_model('rcord', 'RCORDSubscriber')
+
+        for s in subscribers.objects.all():
+            s.downstream_bps = bp
+            s.upstream_bps = bp
+            s.save()
+
+    dependencies = [
+        ('rcord', '0004_bandwidth_profiles'),
+    ]
+
+    operations = [
+        migrations.RunPython(forwards),
+    ]
diff --git a/xos/synchronizer/migrations/0006_bandwidth_profiles_required.py b/xos/synchronizer/migrations/0006_bandwidth_profiles_required.py
new file mode 100644
index 0000000..6195923
--- /dev/null
+++ b/xos/synchronizer/migrations/0006_bandwidth_profiles_required.py
@@ -0,0 +1,40 @@
+# Copyright 2017-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.11 on 2019-03-15 20:28
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('rcord', '0005_migrate_bandwidth_profiles'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='rcordsubscriber_decl',
+            name='downstream_bps',
+            field=models.ForeignKey(help_text=b'The subscriber the IP address belongs to', on_delete=django.db.models.deletion.CASCADE, related_name='ds_subscriber', to='rcord.BandwidthProfile_decl'),
+        ),
+        migrations.AlterField(
+            model_name='rcordsubscriber_decl',
+            name='upstream_bps',
+            field=models.ForeignKey(help_text=b'The subscriber the IP address belongs to', on_delete=django.db.models.deletion.CASCADE, related_name='us_subscriber', to='rcord.BandwidthProfile_decl'),
+        ),
+    ]
diff --git a/xos/synchronizer/models/models.py b/xos/synchronizer/models/models.py
index a9fbace..aa859ea 100644
--- a/xos/synchronizer/models/models.py
+++ b/xos/synchronizer/models/models.py
@@ -17,7 +17,11 @@
 import random
 
 from xos.exceptions import XOSValidationError, XOSProgrammingError, XOSPermissionDenied
-from models_decl import RCORDService_decl, RCORDSubscriber_decl, RCORDIpAddress_decl
+from models_decl import RCORDService_decl, RCORDSubscriber_decl, RCORDIpAddress_decl, BandwidthProfile_decl
+
+class BandwidthProfile(BandwidthProfile_decl):
+    class Meta:
+        proxy = True
 
 class RCORDService(RCORDService_decl):
     class Meta:
diff --git a/xos/synchronizer/models/rcord.xproto b/xos/synchronizer/models/rcord.xproto
index 13df2f6..0e84d0f 100644
--- a/xos/synchronizer/models/rcord.xproto
+++ b/xos/synchronizer/models/rcord.xproto
@@ -12,6 +12,19 @@
         max_length = 30];
 }
 
+message BandwidthProfile(XOSBase) {
+    option verbose_name = "Bandwidth Profile";
+    option description = "The Bandwidth Profile assinged to a residential subscriber";
+
+    // TODO add help_text
+    required string name = 3;
+    required int32 cir = 4;
+    required int32 cbs = 5;
+    required int32 eir = 6;
+    required int32 ebs = 7;
+    required int32 air = 8;
+}
+
 message RCORDSubscriber (ServiceInstance) {
     option kind = "RCORDSubscriber";
     option verbose_name = "RCORD Subscriber";
@@ -50,6 +63,11 @@
         help_text = "Option 82 Circuit ID for DHCP relay agent"];
     optional string remote_id = 22 [
         help_text = "Option 82 Remote ID for DHCP relay agent"];
+
+    required manytoone upstream_bps->BandwidthProfile:us_subscriber = 31:1001 [
+        help_text = "The subscriber the IP address belongs to"];
+    required manytoone downstream_bps->BandwidthProfile:ds_subscriber = 32:1002 [
+        help_text = "The subscriber the IP address belongs to"];
 }
 
 message RCORDIpAddress(XOSBase) {