blob: 1db6f26b0527934adff7a420b9a0646d1ef56c2c [file] [log] [blame]
Scott Bakerbba67b62019-01-28 17:38:21 -08001# Copyright 2017-present Open Networking Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
Zack Williams5c2ea232019-01-30 15:23:01 -070015from __future__ import absolute_import
16
Scott Bakerbba67b62019-01-28 17:38:21 -080017import os
Scott Bakerbba67b62019-01-28 17:38:21 -080018import subprocess
19
Zack Williams5c2ea232019-01-30 15:23:01 -070020try:
21 # Python 2 has separate pickle and cPickle
22 # pylint: disable=W1648
23 import cPickle
24except ImportError:
25 # Python 3 will use cPickle by dfault
26 import pickle as cPickle
27
Scott Bakerbba67b62019-01-28 17:38:21 -080028"""
29 Support for autogenerating mock_modelaccessor.
30
31 Each unit test might have its own requirements for the set of xprotos that make
32 up its model testing framework. These should always include the core, and
33 optionally include one or more services.
34"""
35
36
37def build_mock_modelaccessor(
38 dest_dir, xos_dir, services_dir, service_xprotos, target="mock_classes.xtarget"
39):
Scott Bakerc2fddaa2019-01-30 15:45:03 -080040 # TODO: deprecate the dest_dir argument
41
42 # force modelaccessor to be found in /tmp
Zack Williams5c2ea232019-01-30 15:23:01 -070043 dest_dir = "/tmp/mock_modelaccessor"
Scott Bakerc2fddaa2019-01-30 15:45:03 -080044 if not os.path.exists(dest_dir):
45 os.makedirs(dest_dir)
Scott Bakerbba67b62019-01-28 17:38:21 -080046 dest_fn = os.path.join(dest_dir, "mock_modelaccessor.py")
47
48 args = ["xosgenx", "--target", target]
49 args.append(os.path.join(xos_dir, "core/models/core.xproto"))
50 for xproto in service_xprotos:
51 args.append(os.path.join(services_dir, xproto))
52
53 # Check to see if we've already run xosgenx. If so, don't run it again.
54 context_fn = dest_fn + ".context"
55 this_context = (xos_dir, services_dir, service_xprotos, target)
Zack Williams5c2ea232019-01-30 15:23:01 -070056
Scott Bakerbba67b62019-01-28 17:38:21 -080057 if os.path.exists(context_fn):
58 try:
Zack Williams5c2ea232019-01-30 15:23:01 -070059 context = cPickle.loads(open(context_fn, 'rb').read())
Scott Bakerbba67b62019-01-28 17:38:21 -080060 if context == this_context:
61 return
Zack Williams5c2ea232019-01-30 15:23:01 -070062 except (cPickle.UnpicklingError, EOFError, ValueError):
Scott Bakerbba67b62019-01-28 17:38:21 -080063 # Something went wrong with the file read or depickling
64 pass
65
66 if os.path.exists(context_fn):
67 os.remove(context_fn)
68
69 if os.path.exists(dest_fn):
70 os.remove(dest_fn)
71
72 p = subprocess.Popen(
73 " ".join(args) + " > " + dest_fn,
74 shell=True,
75 stdout=subprocess.PIPE,
76 stderr=subprocess.STDOUT,
77 )
78 (stdoutdata, stderrdata) = p.communicate()
79 if (p.returncode != 0) or (not os.path.exists(dest_fn)):
80 raise Exception(
81 "Failed to create mock model accessor, returncode=%d, stdout=%s"
82 % (p.returncode, stdoutdata)
83 )
84
85 # Save the context of this invocation of xosgenx
Zack Williams5c2ea232019-01-30 15:23:01 -070086 open(context_fn, "wb").write(cPickle.dumps(this_context))
87
Scott Bakerc2fddaa2019-01-30 15:45:03 -080088
89# generate model from xproto
90def get_models_fn(services_dir, service_name, xproto_name):
91 name = os.path.join(service_name, "xos", xproto_name)
92 if os.path.exists(os.path.join(services_dir, name)):
93 return name
94 else:
95 name = os.path.join(service_name, "xos", "synchronizer", "models", xproto_name)
96 if os.path.exists(os.path.join(services_dir, name)):
97 return name
98 raise Exception("Unable to find service=%s xproto=%s" % (service_name, xproto_name))
Zack Williams5c2ea232019-01-30 15:23:01 -070099
100
Scott Bakerc2fddaa2019-01-30 15:45:03 -0800101# END generate model from xproto
102
Zack Williams5c2ea232019-01-30 15:23:01 -0700103
Scott Bakerc2fddaa2019-01-30 15:45:03 -0800104def mock_modelaccessor_config(test_dir, services):
105 """ Automatically configure the mock modelaccessor.
106
107 We start from the test directory, and then back up until we find the orchestration directory. From there we
108 can find the other xproto (core, services) that we need to build the mock modelaccessor.
109 """
110
111 orchestration_dir = test_dir
112 while not orchestration_dir.endswith("orchestration"):
113 # back up a level
114 orchestration_dir = os.path.dirname(orchestration_dir)
Zack Williams5c2ea232019-01-30 15:23:01 -0700115 if len(orchestration_dir) < 10:
Scott Bakerc2fddaa2019-01-30 15:45:03 -0800116 raise Exception("Failed to autodiscovery repository tree")
117
118 xos_dir = os.path.join(orchestration_dir, "xos", "xos")
119 services_dir = os.path.join(orchestration_dir, "xos_services")
120
Zack Williams5c2ea232019-01-30 15:23:01 -0700121 service_xprotos = []
Scott Bakerc2fddaa2019-01-30 15:45:03 -0800122 for (service_name, xproto_name) in services:
123 service_xprotos.append(get_models_fn(services_dir, service_name, xproto_name))
124
125 build_mock_modelaccessor(None, xos_dir, services_dir, service_xprotos)