summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKanagaraj Manickam <mkr1481@gmail.com>2016-03-23 15:25:02 +0530
committerKanagaraj Manickam <mkr1481@gmail.com>2016-03-23 15:25:02 +0530
commit0a765fe3ae8aed285dea9e96b21b0cf96b4b12f2 (patch)
tree417047780a019ae03b9787b9c8b01cb989ab226c
parenteca5fb1b5c5c3948fa8536f50c704f3a471fa607 (diff)
FIX-1237 register_myself in manager is resilient
Notes
Notes (review): Code-Review+2: Kanagaraj Manickam <mkr1481@gmail.com> Workflow+1: Kanagaraj Manickam <mkr1481@gmail.com> Verified+2: Jenkins Submitted-by: Jenkins Submitted-at: Mon, 18 Apr 2016 10:37:18 +0000 Reviewed-on: https://review.openstack.org/307062 Project: openstack/namos Branch: refs/heads/master
-rw-r--r--etc/namos.conf2
-rw-r--r--namos/cmd/conductor.py3
-rw-r--r--namos/common/exception.py6
-rw-r--r--namos/conductor/manager.py193
-rw-r--r--namos/db/sqlalchemy/alembic/versions/48ebec3cd6f6_initial_version.py19
-rw-r--r--namos/db/sqlalchemy/api.py7
-rw-r--r--namos/db/sqlalchemy/models.py42
7 files changed, 165 insertions, 107 deletions
diff --git a/etc/namos.conf b/etc/namos.conf
index 4e24ccd..e416c87 100644
--- a/etc/namos.conf
+++ b/etc/namos.conf
@@ -10,4 +10,4 @@ rabbit_hosts = 172.241.0.101
10connection = mysql+pymysql://root:password@172.241.0.101/namos?charset=utf8 10connection = mysql+pymysql://root:password@172.241.0.101/namos?charset=utf8
11 11
12[conductor] 12[conductor]
13workers=10 \ No newline at end of file 13workers=1 \ No newline at end of file
diff --git a/namos/cmd/conductor.py b/namos/cmd/conductor.py
index 9cffa51..32ab4a4 100644
--- a/namos/cmd/conductor.py
+++ b/namos/cmd/conductor.py
@@ -50,7 +50,8 @@ def main():
50 launcher = os_service.launch(CONF, mgr, CONF.conductor.workers) 50 launcher = os_service.launch(CONF, mgr, CONF.conductor.workers)
51 51
52 # TODO(mrkanag) Namos is not registering the RPC backend, fix it ! 52 # TODO(mrkanag) Namos is not registering the RPC backend, fix it !
53 # namos.register_myself() 53 import os_namos
54 os_namos.register_myself()
54 55
55 launcher.wait() 56 launcher.wait()
56 57
diff --git a/namos/common/exception.py b/namos/common/exception.py
index d9da06f..403bd0e 100644
--- a/namos/common/exception.py
+++ b/namos/common/exception.py
@@ -63,6 +63,12 @@ class NotFound(NamosException):
63 http_status_code = 404 63 http_status_code = 404
64 64
65 65
66class AlreadyExist(NamosException):
67 msg_fmt = ("%(model)s %(name)s already exists")
68 error_code = 0x01002
69 http_status_code = 403
70
71
66class RegionNotFound(NotFound): 72class RegionNotFound(NotFound):
67 msg_fmt = ("Region %(region_id)s does not found") 73 msg_fmt = ("Region %(region_id)s does not found")
68 error_code = 0x01001 74 error_code = 0x01001
diff --git a/namos/conductor/manager.py b/namos/conductor/manager.py
index 7e929ea..559a0bb 100644
--- a/namos/conductor/manager.py
+++ b/namos/conductor/manager.py
@@ -129,12 +129,6 @@ class ServiceProcessor(object):
129 def process_service(self, context): 129 def process_service(self, context):
130 # Service Node 130 # Service Node
131 try: 131 try:
132 # TODO(mrkanag) is this to be region specifc search
133 node = db_api.service_node_get_by_name(
134 context,
135 self.registration_info.get('fqdn'))
136 LOG.info('Service node %s is existing' % node)
137 except exception.ServiceNodeNotFound:
138 # TODO(mrkanag) region_id is hard-coded, fix it ! 132 # TODO(mrkanag) region_id is hard-coded, fix it !
139 # user proper node name instead of fqdn 133 # user proper node name instead of fqdn
140 node = db_api.service_node_create( 134 node = db_api.service_node_create(
@@ -144,14 +138,15 @@ class ServiceProcessor(object):
144 region_id='f7dcd175-27ef-46b5-997f-e6e572f320b0')) 138 region_id='f7dcd175-27ef-46b5-997f-e6e572f320b0'))
145 139
146 LOG.info('Service node %s is created' % node) 140 LOG.info('Service node %s is created' % node)
141 except exception.AlreadyExist:
142 # TODO(mrkanag) is this to be region specifc search
143 node = db_api.service_node_get_by_name(
144 context,
145 self.registration_info.get('fqdn'))
146 LOG.info('Service node %s is existing' % node)
147 147
148 # Service 148 # Service
149 try: 149 try:
150 service = db_api.service_get_by_name(
151 context,
152 self.registration_info.get('project_name'))
153 LOG.info('Service %s is existing' % service)
154 except exception.ServiceNotFound:
155 s_id = 'b9c2549f-f685-4bc2-92e9-ba8af9c18591' 150 s_id = 'b9c2549f-f685-4bc2-92e9-ba8af9c18591'
156 service = db_api.service_create( 151 service = db_api.service_create(
157 context, 152 context,
@@ -161,53 +156,36 @@ class ServiceProcessor(object):
161 keystone_service_id=s_id)) 156 keystone_service_id=s_id))
162 157
163 LOG.info('Service %s is created' % service) 158 LOG.info('Service %s is created' % service)
159 except exception.AlreadyExist:
160 service = db_api.service_get_by_name(
161 context,
162 self.registration_info.get('project_name'))
163 LOG.info('Service %s is existing' % service)
164 164
165 # Service Component 165 # Service Component
166 service_components = \ 166 try:
167 db_api.service_component_get_all_by_node_for_service(
168 context,
169 node_id=node.id,
170 service_id=service.id,
171 name=self.registration_info['prog_name']
172 )
173 if len(service_components) == 1:
174 service_component = service_components[0]
175 LOG.info('Service Component %s is existing' % service_component)
176 # TODO(mrkanag) what to do when service_components size is > 1
177 else:
178 service_component = db_api.service_component_create( 167 service_component = db_api.service_component_create(
179 context, 168 context,
180 dict(name=self.registration_info['prog_name'], 169 dict(name=self.registration_info['prog_name'],
181 node_id=node.id, 170 node_id=node.id,
182 service_id=service.id)) 171 service_id=service.id))
183 LOG.info('Service Component %s is created' % service_component) 172 LOG.info('Service Component %s is created' % service_component)
173 except exception.AlreadyExist:
174 service_components = \
175 db_api.service_component_get_all_by_node_for_service(
176 context,
177 node_id=node.id,
178 service_id=service.id,
179 name=self.registration_info['prog_name']
180 )
181 if len(service_components) == 1:
182 service_component = service_components[0]
183 LOG.info('Service Component %s is existing' %
184 service_component)
185 # TODO(mrkanag) what to do when service_components size is > 1
184 186
185 # Service Worker 187 # Service Worker
186 # TODO(mrkanag) Find a way to purge the dead service worker 188 try:
187 # Once each service is enabled with heart beating namos
188 # purging can be done once heart beat stopped. this can be
189 # done from openstack.common.service.py
190 service_workers = \
191 db_api.service_worker_get_by_host_for_service_component(
192 context,
193 service_component_id=service_component.id,
194 host=self.registration_info['host']
195 )
196 if len(service_workers) == 1:
197 service_worker = \
198 db_api.service_worker_update(
199 context,
200 service_workers[0].id,
201 dict(
202 pid=self.registration_info['pid'],
203 name='%s@%s' % (self.registration_info['pid'],
204 service_component.name)
205 ))
206 LOG.info('Service Worker %s is existing and is updated'
207 % service_worker)
208
209 # TODO(mrkanag) what to do when service_workers size is > 1
210 else:
211 service_worker = db_api.service_worker_create( 189 service_worker = db_api.service_worker_create(
212 context, 190 context,
213 # TODO(mrkanag) Fix the name, device driver proper ! 191 # TODO(mrkanag) Fix the name, device driver proper !
@@ -217,6 +195,31 @@ class ServiceProcessor(object):
217 host=self.registration_info['host'], 195 host=self.registration_info['host'],
218 service_component_id=service_component.id)) 196 service_component_id=service_component.id))
219 LOG.info('Service Worker %s is created' % service_worker) 197 LOG.info('Service Worker %s is created' % service_worker)
198 except exception.AlreadyExist:
199 # TODO(mrkanag) Find a way to purge the dead service worker
200 # Once each service is enabled with heart beating namos
201 # purging can be done once heart beat stopped. this can be
202 # done from openstack.common.service.py
203 service_workers = \
204 db_api.service_worker_get_by_host_for_service_component(
205 context,
206 service_component_id=service_component.id,
207 host=self.registration_info['host']
208 )
209 if len(service_workers) == 1:
210 service_worker = \
211 db_api.service_worker_update(
212 context,
213 service_workers[0].id,
214 dict(
215 pid=self.registration_info['pid'],
216 name='%s@%s' % (self.registration_info['pid'],
217 service_component.name)
218 ))
219 LOG.info('Service Worker %s is existing and is updated'
220 % service_worker)
221
222 # TODO(mrkanag) what to do when service_workers size is > 1
220 223
221 # Config 224 # Config
222 # TODO(mrkanag) Optimize the config like per service_component 225 # TODO(mrkanag) Optimize the config like per service_component
@@ -224,18 +227,20 @@ class ServiceProcessor(object):
224 for cfg_name, cfg_obj in self.registration_info[ 227 for cfg_name, cfg_obj in self.registration_info[
225 'config_dict'].iteritems(): 228 'config_dict'].iteritems():
226 cfg_obj['service_worker_id'] = service_worker.id 229 cfg_obj['service_worker_id'] = service_worker.id
227 configs = db_api.config_get_by_name_for_service_worker( 230
228 context, 231 try:
229 service_worker_id=cfg_obj['service_worker_id'],
230 name=cfg_obj['name'])
231 if len(configs) == 1:
232 config = db_api.config_update(context,
233 configs[0].id,
234 cfg_obj)
235 LOG.info("Config %s is existing and is updated" % config)
236 else:
237 config = db_api.config_create(context, cfg_obj) 232 config = db_api.config_create(context, cfg_obj)
238 LOG.info("Config %s is created" % config) 233 LOG.info("Config %s is created" % config)
234 except exception.AlreadyExist:
235 configs = db_api.config_get_by_name_for_service_worker(
236 context,
237 service_worker_id=cfg_obj['service_worker_id'],
238 name=cfg_obj['name'])
239 if len(configs) == 1:
240 config = db_api.config_update(context,
241 configs[0].id,
242 cfg_obj)
243 LOG.info("Config %s is existing and is updated" % config)
239 244
240 return service_worker.id 245 return service_worker.id
241 246
@@ -367,11 +372,6 @@ class DriverProcessor(object):
367 # Device 372 # Device
368 device_name = self._get_value(device_cfg['name']) 373 device_name = self._get_value(device_cfg['name'])
369 try: 374 try:
370 device = db_api.device_get_by_name(
371 context,
372 device_name)
373 LOG.info('Device %s is existing' % device)
374 except exception.DeviceNotFound:
375 # TODO(mrkanag) region_id is hard-coded, fix it ! 375 # TODO(mrkanag) region_id is hard-coded, fix it !
376 # Set the right status as well 376 # Set the right status as well
377 device = db_api.device_create( 377 device = db_api.device_create(
@@ -381,8 +381,13 @@ class DriverProcessor(object):
381 region_id='f7dcd175-27ef-46b5-997f-e6e572f320b0')) 381 region_id='f7dcd175-27ef-46b5-997f-e6e572f320b0'))
382 382
383 LOG.info('Device %s is created' % device) 383 LOG.info('Device %s is created' % device)
384 except exception.AlreadyExist:
385 device = db_api.device_get_by_name(
386 context,
387 device_name)
388 LOG.info('Device %s is existing' % device)
384 389
385 # Handle child devices 390 # TODO(mrkanag) Poperly Handle child devices
386 if child_device_cfg is not None: 391 if child_device_cfg is not None:
387 for d_name in self._get_value(child_device_cfg['key']): 392 for d_name in self._get_value(child_device_cfg['key']):
388 base_name = self._get_value(child_device_cfg['base_name']) 393 base_name = self._get_value(child_device_cfg['base_name'])
@@ -406,16 +411,7 @@ class DriverProcessor(object):
406 LOG.info('Device %s is created' % device) 411 LOG.info('Device %s is created' % device)
407 412
408 # Device Endpoint 413 # Device Endpoint
409 device_endpoints = db_api.device_endpoint_get_by_device_type( 414 try:
410 context,
411 device_id=device.id,
412 type=endpoint_type,
413 name=device_endpoint_name)
414 if len(device_endpoints) >= 1:
415 device_endpoint = device_endpoints[0]
416 LOG.info('Device Endpoint %s is existing' %
417 device_endpoints[0])
418 else:
419 for k, v in connection_cfg.iteritems(): 415 for k, v in connection_cfg.iteritems():
420 connection[k] = self._get_value(k) 416 connection[k] = self._get_value(k)
421 417
@@ -426,15 +422,19 @@ class DriverProcessor(object):
426 type=endpoint_type, 422 type=endpoint_type,
427 device_id=device.id)) 423 device_id=device.id))
428 LOG.info('Device Endpoint %s is created' % device_endpoint) 424 LOG.info('Device Endpoint %s is created' % device_endpoint)
425 except exception.AlreadyExist:
426 device_endpoints = db_api.device_endpoint_get_by_device_type(
427 context,
428 device_id=device.id,
429 type=endpoint_type,
430 name=device_endpoint_name)
431 if len(device_endpoints) >= 1:
432 device_endpoint = device_endpoints[0]
433 LOG.info('Device Endpoint %s is existing' %
434 device_endpoints[0])
429 435
430 # Device Driver Class 436 # Device Driver Class
431 try: 437 try:
432 device_driver_class = db_api.device_driver_class_get_by_name(
433 context,
434 driver_name)
435 LOG.info('Device Driver Class %s is existing' %
436 device_driver_class)
437 except exception.DeviceDriverClassNotFound:
438 device_driver_class = db_api.device_driver_class_create( 438 device_driver_class = db_api.device_driver_class_create(
439 context, 439 context,
440 dict(name=driver_name, 440 dict(name=driver_name,
@@ -446,21 +446,15 @@ class DriverProcessor(object):
446 extra=driver_def.get('extra'))) 446 extra=driver_def.get('extra')))
447 LOG.info('Device Driver Class %s is created' % 447 LOG.info('Device Driver Class %s is created' %
448 device_driver_class) 448 device_driver_class)
449 except exception.AlreadyExist:
450 device_driver_class = db_api.device_driver_class_get_by_name(
451 context,
452 driver_name)
453 LOG.info('Device Driver Class %s is existing' %
454 device_driver_class)
449 455
450 # Device Driver 456 # Device Driver
451 device_drivers = \ 457 try:
452 db_api.device_driver_get_by_device_endpoint_service_worker(
453 context,
454 device_id=device.id,
455 endpoint_id=device_endpoint.id,
456 device_driver_class_id=device_driver_class.id,
457 service_worker_id=self.service_worker_id
458 )
459 if len(device_drivers) >= 1:
460 device_driver = device_drivers[0]
461 LOG.info('Device Driver %s is existing' %
462 device_driver)
463 else:
464 device_driver = db_api.device_driver_create( 458 device_driver = db_api.device_driver_create(
465 context, 459 context,
466 dict(device_id=device.id, 460 dict(device_id=device.id,
@@ -471,6 +465,19 @@ class DriverProcessor(object):
471 ) 465 )
472 LOG.info('Device Driver %s is created' % 466 LOG.info('Device Driver %s is created' %
473 device_driver) 467 device_driver)
468 except exception.AlreadyExist:
469 device_drivers = \
470 db_api.device_driver_get_by_device_endpoint_service_worker(
471 context,
472 device_id=device.id,
473 endpoint_id=device_endpoint.id,
474 device_driver_class_id=device_driver_class.id,
475 service_worker_id=self.service_worker_id
476 )
477 if len(device_drivers) >= 1:
478 device_driver = device_drivers[0]
479 LOG.info('Device Driver %s is existing' %
480 device_driver)
474 481
475 482
476if __name__ == '__main__': 483if __name__ == '__main__':
diff --git a/namos/db/sqlalchemy/alembic/versions/48ebec3cd6f6_initial_version.py b/namos/db/sqlalchemy/alembic/versions/48ebec3cd6f6_initial_version.py
index 83679a5..a9e5d39 100644
--- a/namos/db/sqlalchemy/alembic/versions/48ebec3cd6f6_initial_version.py
+++ b/namos/db/sqlalchemy/alembic/versions/48ebec3cd6f6_initial_version.py
@@ -34,7 +34,7 @@ def upgrade():
34 sa.Column('created_at', sa.DateTime(), nullable=True), 34 sa.Column('created_at', sa.DateTime(), nullable=True),
35 sa.Column('updated_at', sa.DateTime(), nullable=True), 35 sa.Column('updated_at', sa.DateTime(), nullable=True),
36 sa.Column('id', sa.Uuid(length=36), nullable=False), 36 sa.Column('id', sa.Uuid(length=36), nullable=False),
37 sa.Column('name', sa.String(length=255), nullable=False), 37 sa.Column('name', sa.String(length=255), nullable=False, unique=True),
38 sa.Column('deleted_at', sa.DateTime(), nullable=True), 38 sa.Column('deleted_at', sa.DateTime(), nullable=True),
39 sa.Column('extra', sa.Json(), nullable=True), 39 sa.Column('extra', sa.Json(), nullable=True),
40 sa.Column('keystone_service_id', sa.Uuid(length=36), nullable=False), 40 sa.Column('keystone_service_id', sa.Uuid(length=36), nullable=False),
@@ -47,7 +47,7 @@ def upgrade():
47 sa.Column('created_at', sa.DateTime(), nullable=True), 47 sa.Column('created_at', sa.DateTime(), nullable=True),
48 sa.Column('updated_at', sa.DateTime(), nullable=True), 48 sa.Column('updated_at', sa.DateTime(), nullable=True),
49 sa.Column('id', sa.Uuid(length=36), nullable=False), 49 sa.Column('id', sa.Uuid(length=36), nullable=False),
50 sa.Column('name', sa.String(length=255), nullable=False), 50 sa.Column('name', sa.String(length=255), nullable=False, unique=True),
51 sa.Column('deleted_at', sa.DateTime(), nullable=True), 51 sa.Column('deleted_at', sa.DateTime(), nullable=True),
52 sa.Column('extra', sa.Json(), nullable=True), 52 sa.Column('extra', sa.Json(), nullable=True),
53 sa.Column('python_class', sa.String(length=256), nullable=False), 53 sa.Column('python_class', sa.String(length=256), nullable=False),
@@ -62,7 +62,7 @@ def upgrade():
62 sa.Column('created_at', sa.DateTime(), nullable=True), 62 sa.Column('created_at', sa.DateTime(), nullable=True),
63 sa.Column('updated_at', sa.DateTime(), nullable=True), 63 sa.Column('updated_at', sa.DateTime(), nullable=True),
64 sa.Column('id', sa.Uuid(length=36), nullable=False), 64 sa.Column('id', sa.Uuid(length=36), nullable=False),
65 sa.Column('name', sa.String(length=255), nullable=False), 65 sa.Column('name', sa.String(length=255), nullable=False, unique=True),
66 sa.Column('deleted_at', sa.DateTime(), nullable=True), 66 sa.Column('deleted_at', sa.DateTime(), nullable=True),
67 sa.Column('extra', sa.Json(), nullable=True), 67 sa.Column('extra', sa.Json(), nullable=True),
68 sa.Column('keystone_region_id', sa.String(length=255), nullable=False), 68 sa.Column('keystone_region_id', sa.String(length=255), nullable=False),
@@ -75,7 +75,7 @@ def upgrade():
75 sa.Column('created_at', sa.DateTime(), nullable=True), 75 sa.Column('created_at', sa.DateTime(), nullable=True),
76 sa.Column('updated_at', sa.DateTime(), nullable=True), 76 sa.Column('updated_at', sa.DateTime(), nullable=True),
77 sa.Column('id', sa.Uuid(length=36), nullable=False), 77 sa.Column('id', sa.Uuid(length=36), nullable=False),
78 sa.Column('name', sa.String(length=255), nullable=False), 78 sa.Column('name', sa.String(length=255), nullable=False, unique=True),
79 sa.Column('deleted_at', sa.DateTime(), nullable=True), 79 sa.Column('deleted_at', sa.DateTime(), nullable=True),
80 sa.Column('status', sa.String(length=64), nullable=False), 80 sa.Column('status', sa.String(length=64), nullable=False),
81 sa.Column('description', sa.Text(), nullable=True), 81 sa.Column('description', sa.Text(), nullable=True),
@@ -94,7 +94,7 @@ def upgrade():
94 sa.Column('created_at', sa.DateTime(), nullable=True), 94 sa.Column('created_at', sa.DateTime(), nullable=True),
95 sa.Column('updated_at', sa.DateTime(), nullable=True), 95 sa.Column('updated_at', sa.DateTime(), nullable=True),
96 sa.Column('id', sa.Uuid(length=36), nullable=False), 96 sa.Column('id', sa.Uuid(length=36), nullable=False),
97 sa.Column('name', sa.String(length=255), nullable=False), 97 sa.Column('name', sa.String(length=255), nullable=False, unique=True),
98 sa.Column('deleted_at', sa.DateTime(), nullable=True), 98 sa.Column('deleted_at', sa.DateTime(), nullable=True),
99 sa.Column('description', sa.Text(), nullable=True), 99 sa.Column('description', sa.Text(), nullable=True),
100 sa.Column('extra', sa.Json(), nullable=True), 100 sa.Column('extra', sa.Json(), nullable=True),
@@ -110,7 +110,7 @@ def upgrade():
110 sa.Column('created_at', sa.DateTime(), nullable=True), 110 sa.Column('created_at', sa.DateTime(), nullable=True),
111 sa.Column('updated_at', sa.DateTime(), nullable=True), 111 sa.Column('updated_at', sa.DateTime(), nullable=True),
112 sa.Column('id', sa.Uuid(length=36), nullable=False), 112 sa.Column('id', sa.Uuid(length=36), nullable=False),
113 sa.Column('name', sa.String(length=255), nullable=False), 113 sa.Column('name', sa.String(length=255), nullable=False, unique=True),
114 sa.Column('extra', sa.Json(), nullable=True), 114 sa.Column('extra', sa.Json(), nullable=True),
115 sa.Column('device_id', sa.Uuid(length=36), nullable=True), 115 sa.Column('device_id', sa.Uuid(length=36), nullable=True),
116 sa.Column('connection', sa.Json(), nullable=False), 116 sa.Column('connection', sa.Json(), nullable=False),
@@ -124,7 +124,7 @@ def upgrade():
124 sa.Column('created_at', sa.DateTime(), nullable=True), 124 sa.Column('created_at', sa.DateTime(), nullable=True),
125 sa.Column('updated_at', sa.DateTime(), nullable=True), 125 sa.Column('updated_at', sa.DateTime(), nullable=True),
126 sa.Column('id', sa.Uuid(length=36), nullable=False), 126 sa.Column('id', sa.Uuid(length=36), nullable=False),
127 sa.Column('name', sa.String(length=255), nullable=False), 127 sa.Column('name', sa.String(length=255), nullable=False, unique=True),
128 sa.Column('deleted_at', sa.DateTime(), nullable=True), 128 sa.Column('deleted_at', sa.DateTime(), nullable=True),
129 sa.Column('description', sa.Text(), nullable=True), 129 sa.Column('description', sa.Text(), nullable=True),
130 sa.Column('extra', sa.Json(), nullable=True), 130 sa.Column('extra', sa.Json(), nullable=True),
@@ -141,7 +141,7 @@ def upgrade():
141 sa.Column('created_at', sa.DateTime(), nullable=True), 141 sa.Column('created_at', sa.DateTime(), nullable=True),
142 sa.Column('updated_at', sa.DateTime(), nullable=True), 142 sa.Column('updated_at', sa.DateTime(), nullable=True),
143 sa.Column('id', sa.Uuid(length=36), nullable=False), 143 sa.Column('id', sa.Uuid(length=36), nullable=False),
144 sa.Column('name', sa.String(length=255), nullable=False), 144 sa.Column('name', sa.String(length=255), nullable=False, unique=True),
145 sa.Column('deleted_at', sa.DateTime(), nullable=True), 145 sa.Column('deleted_at', sa.DateTime(), nullable=True),
146 sa.Column('extra', sa.Json(), nullable=True), 146 sa.Column('extra', sa.Json(), nullable=True),
147 sa.Column('endpoint_id', sa.Uuid(length=36), nullable=True), 147 sa.Column('endpoint_id', sa.Uuid(length=36), nullable=True),
@@ -160,7 +160,7 @@ def upgrade():
160 sa.Column('created_at', sa.DateTime(), nullable=True), 160 sa.Column('created_at', sa.DateTime(), nullable=True),
161 sa.Column('updated_at', sa.DateTime(), nullable=True), 161 sa.Column('updated_at', sa.DateTime(), nullable=True),
162 sa.Column('id', sa.Uuid(length=36), nullable=False), 162 sa.Column('id', sa.Uuid(length=36), nullable=False),
163 sa.Column('name', sa.String(length=255), nullable=False), 163 sa.Column('name', sa.String(length=255), nullable=False, unique=True),
164 sa.Column('deleted_at', sa.DateTime(), nullable=True), 164 sa.Column('deleted_at', sa.DateTime(), nullable=True),
165 sa.Column('extra', sa.Json(), nullable=True), 165 sa.Column('extra', sa.Json(), nullable=True),
166 sa.Column('pid', sa.String(length=32), nullable=False), 166 sa.Column('pid', sa.String(length=32), nullable=False),
@@ -173,6 +173,7 @@ def upgrade():
173 sa.PrimaryKeyConstraint('id'), 173 sa.PrimaryKeyConstraint('id'),
174 mysql_engine='InnoDB' 174 mysql_engine='InnoDB'
175 ) 175 )
176# TODO(mrkanag) add oslo_config schema here
176 177
177 178
178def downgrade(): 179def downgrade():
diff --git a/namos/db/sqlalchemy/api.py b/namos/db/sqlalchemy/api.py
index a889576..d9a5ad8 100644
--- a/namos/db/sqlalchemy/api.py
+++ b/namos/db/sqlalchemy/api.py
@@ -16,6 +16,7 @@
16import sys 16import sys
17 17
18from oslo_config import cfg 18from oslo_config import cfg
19from oslo_db import exception as db_exception
19from oslo_db.sqlalchemy import session as db_session 20from oslo_db.sqlalchemy import session as db_session
20 21
21from namos.common import exception 22from namos.common import exception
@@ -57,7 +58,11 @@ def _session(context):
57 58
58def _create(context, resource_ref, values): 59def _create(context, resource_ref, values):
59 resource_ref.update(values) 60 resource_ref.update(values)
60 resource_ref.save(_session(context)) 61 try:
62 resource_ref.save(_session(context))
63 except db_exception.DBDuplicateEntry:
64 raise exception.AlreadyExist(model=resource_ref.__class__.__name__,
65 name=resource_ref.name)
61 return resource_ref 66 return resource_ref
62 67
63 68
diff --git a/namos/db/sqlalchemy/models.py b/namos/db/sqlalchemy/models.py
index 0cae56b..7483dfe 100644
--- a/namos/db/sqlalchemy/models.py
+++ b/namos/db/sqlalchemy/models.py
@@ -18,6 +18,7 @@ SQLAlchemy models for namos database
18 18
19import sqlalchemy 19import sqlalchemy
20from sqlalchemy.ext.declarative import declarative_base 20from sqlalchemy.ext.declarative import declarative_base
21from sqlalchemy import UniqueConstraint
21import uuid 22import uuid
22 23
23from namos.db.sqlalchemy.types import Json 24from namos.db.sqlalchemy.types import Json
@@ -37,7 +38,7 @@ class NamosBase(models.ModelBase,
37 id = sqlalchemy.Column(Uuid, primary_key=True, 38 id = sqlalchemy.Column(Uuid, primary_key=True,
38 default=lambda: str(uuid.uuid4())) 39 default=lambda: str(uuid.uuid4()))
39 name = sqlalchemy.Column(sqlalchemy.String(255), 40 name = sqlalchemy.Column(sqlalchemy.String(255),
40 # unique=True, 41 unique=True,
41 nullable=False, 42 nullable=False,
42 default=lambda: str(uuid.uuid4())) 43 default=lambda: str(uuid.uuid4()))
43 44
@@ -128,6 +129,9 @@ class DeviceEndpoint(BASE,
128 Extra): 129 Extra):
129 __tablename__ = 'device_endpoint' 130 __tablename__ = 'device_endpoint'
130 131
132 __table_args__ = (
133 UniqueConstraint("device_id", "type"),
134 )
131 device_id = sqlalchemy.Column( 135 device_id = sqlalchemy.Column(
132 Uuid, 136 Uuid,
133 sqlalchemy.ForeignKey('device.id'), 137 sqlalchemy.ForeignKey('device.id'),
@@ -145,6 +149,12 @@ class DeviceDriver(BASE,
145 SoftDelete, 149 SoftDelete,
146 Extra): 150 Extra):
147 __tablename__ = 'device_driver' 151 __tablename__ = 'device_driver'
152 __table_args__ = (
153 UniqueConstraint("device_id",
154 "endpoint_id",
155 "device_driver_class_id",
156 "service_worker_id"),
157 )
148 158
149 endpoint_id = sqlalchemy.Column( 159 endpoint_id = sqlalchemy.Column(
150 Uuid, 160 Uuid,
@@ -179,7 +189,8 @@ class DeviceDriverClass(BASE,
179 # TODO(kanagaraj-manickam) Correct the max python class path here 189 # TODO(kanagaraj-manickam) Correct the max python class path here
180 python_class = sqlalchemy.Column( 190 python_class = sqlalchemy.Column(
181 sqlalchemy.String(256), 191 sqlalchemy.String(256),
182 nullable=False 192 nullable=False,
193 unique=True
183 ) 194 )
184 # service type like compute, network, volume, etc 195 # service type like compute, network, volume, etc
185 type = sqlalchemy.Column( 196 type = sqlalchemy.Column(
@@ -225,6 +236,15 @@ class ServiceComponent(BASE,
225 Extra): 236 Extra):
226 __tablename__ = 'service_component' 237 __tablename__ = 'service_component'
227 238
239 __table_args__ = (
240 UniqueConstraint("name", "node_id", "service_id"),
241 )
242
243 name = sqlalchemy.Column(sqlalchemy.String(255),
244 # unique=True,
245 nullable=False,
246 default=lambda: str(uuid.uuid4()))
247
228 node_id = sqlalchemy.Column( 248 node_id = sqlalchemy.Column(
229 Uuid, 249 Uuid,
230 sqlalchemy.ForeignKey('service_node.id'), 250 sqlalchemy.ForeignKey('service_node.id'),
@@ -241,6 +261,15 @@ class ServiceWorker(BASE,
241 Extra): 261 Extra):
242 __tablename__ = 'service_worker' 262 __tablename__ = 'service_worker'
243 263
264 __table_args__ = (
265 UniqueConstraint("host", "service_component_id"),
266 )
267
268 name = sqlalchemy.Column(sqlalchemy.String(255),
269 # unique=True,
270 nullable=False,
271 default=lambda: str(uuid.uuid4()))
272
244 pid = sqlalchemy.Column( 273 pid = sqlalchemy.Column(
245 sqlalchemy.String(32), 274 sqlalchemy.String(32),
246 nullable=False 275 nullable=False
@@ -261,9 +290,18 @@ class OsloConfig(BASE,
261 Extra): 290 Extra):
262 __tablename__ = 'oslo_config' 291 __tablename__ = 'oslo_config'
263 292
293 __table_args__ = (
294 UniqueConstraint("name", "service_worker_id"),
295 )
296
264 default_value = sqlalchemy.Column( 297 default_value = sqlalchemy.Column(
265 sqlalchemy.Text 298 sqlalchemy.Text
266 ) 299 )
300 name = sqlalchemy.Column(sqlalchemy.String(255),
301 # unique=True,
302 nullable=False,
303 default=lambda: str(uuid.uuid4()))
304
267 help = sqlalchemy.Column( 305 help = sqlalchemy.Column(
268 sqlalchemy.Text, 306 sqlalchemy.Text,
269 nullable=False, 307 nullable=False,