1 # Copyright (c) 2015 SONATA-NFV and Paderborn University
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 # Neither the name of the SONATA-NFV, Paderborn University
17 # nor the names of its contributors may be used to endorse or promote
18 # products derived from this software without specific prior written
21 # This work has been performed in the framework of the SONATA project,
22 # funded by the European Commission under Grant number 671517 through
23 # the Horizon 2020 and 5G-PPP programmes. The authors would like to
24 # acknowledge the contributions of their colleagues of the SONATA
25 # partner consortium (www.sonata-nfv.eu).
27 LOG
= logging
.getLogger("resourcemodel")
28 LOG
.setLevel(logging
.DEBUG
)
31 class ResourceModelRegistrar(object):
33 Global registry to keep track of all existing resource models.
36 def __init__(self
, dc_emulation_max_cpu
, dc_emulation_max_mem
):
37 self
.e_cpu
= dc_emulation_max_cpu
38 self
.e_mem
= dc_emulation_max_mem
39 # pointer to all resource models assigned to DCs
40 self
._resource
_models
= dict()
41 LOG
.info("Resource model registrar created with dc_emulation_max_cpu=%r and dc_emulation_max_mem=%r"
42 % (dc_emulation_max_cpu
, dc_emulation_max_mem
))
44 def register(self
, dc
, rm
):
46 Register a new resource model.
47 :param dc: Data center to which it is assigned.
48 :param rm: The resource model object.
51 if dc
in self
._resource
_models
:
53 "There is already an resource model assigned to this DC.")
54 self
._resource
_models
[dc
] = rm
57 LOG
.info("Registrar: Added resource model: %r" % rm
)
60 def resource_models(self
):
62 List of registered resource models
65 return list(self
._resource
_models
.itervalues())
68 def num_dcs_with_rms(self
):
70 Total number of data centers that are connected to a resource model
73 return sum([len(rm
.dcs
)
74 for rm
in list(self
._resource
_models
.itervalues())])
77 class ResourceFlavor(object):
79 Simple class that represents resource flavors (c.f. OpenStack).
80 Can contain arbitrary metrics.
83 def __init__(self
, name
, metrics
):
85 self
._metrics
= metrics
86 LOG
.debug("Create flavor %r with metrics: %r" % (name
, metrics
))
88 def get(self
, metric_key
):
89 return self
._metrics
.get(metric_key
)
92 class BaseResourceModel(object):
94 Base class for a resource limitation model.
95 Has to be extended by a real resource model implementtion.
99 self
._flavors
= dict()
100 self
._initDefaultFlavors
()
101 self
.registrar
= None # pointer to registrar
103 self
._allocated
_compute
_instances
= dict()
104 LOG
.info("Resource model %r initialized" % self
)
107 return self
.__class
__.__name
__
109 def _initDefaultFlavors(self
):
111 initialize some default flavours (naming/sizes inspired by OpenStack)
113 self
.addFlavour(ResourceFlavor(
114 "tiny", {"compute": 0.5, "memory": 32, "disk": 1}))
115 self
.addFlavour(ResourceFlavor(
116 "small", {"compute": 1.0, "memory": 128, "disk": 20}))
117 self
.addFlavour(ResourceFlavor(
118 "medium", {"compute": 4.0, "memory": 256, "disk": 40}))
119 self
.addFlavour(ResourceFlavor(
120 "large", {"compute": 8.0, "memory": 512, "disk": 80}))
121 self
.addFlavour(ResourceFlavor(
122 "xlarge", {"compute": 16.0, "memory": 1024, "disk": 160}))
124 def addFlavour(self
, fl
):
126 Add a new flavor to the resource model.
127 :param fl: flavor object
130 if fl
.name
in self
._flavors
:
131 raise Exception("Flavor with name %r already exists!" % fl
.name
)
132 self
._flavors
[fl
.name
] = fl
134 def allocate(self
, d
):
136 This method has to be overwritten by a real resource model.
137 :param d: Container object
139 LOG
.warning("Allocating in BaseResourceModel: %r with flavor: %r" % (
140 d
.name
, d
.flavor_name
))
141 self
._allocated
_compute
_instances
[d
.name
] = d
.flavor_name
145 This method has to be overwritten by a real resource model.
146 :param d: Container object
148 LOG
.warning("Free in BaseResourceModel: %r" % d
.name
)
149 del self
._allocated
_compute
_instances
[d
.name
]
151 def get_state_dict(self
):
153 Return the state of the resource model as simple dict.
154 Helper method for logging functionality.
159 def write_allocation_log(self
, d
, path
):
161 Helper to log RM info for experiments.
163 :param path: log path
166 self
._write
_log
(d
, path
, "allocate")
168 def write_free_log(self
, d
, path
):
170 Helper to log RM info for experiments.
172 :param path: log path
175 self
._write
_log
(d
, path
, "free")
177 def _write_log(self
, d
, path
, action
):
179 Helper to log RM info for experiments.
181 :param path: log path
182 :param action: allocate or free
188 class NotEnoughResourcesAvailable(BaseException
):