1 ##############################################################################
2 # Copyright (c) 2017 Ericsson AB and others.
3 # Author: Jose Lausuch (jose.lausuch@ericsson.com)
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
10 from abc import abstractmethod
14 from opnfv.utils import opnfv_logger as logger
15 from opnfv.utils import ssh_utils
17 logger = logger.Logger(__name__).getLogger()
20 class Deployment(object):
32 self.deployment_info = {
33 'installer': installer,
34 'installer_ip': installer_ip,
38 'openstack_version': openstack_version,
39 'sdn_controller': sdn_controller,
43 def _get_openstack_release(self):
45 Translates an openstack version into the release name
56 version = self.deployment_info['openstack_version'].split('.')[0]
57 name = os_versions[version]
60 return 'Unknown release'
64 Returns a dictionary will all the attributes
66 return self.deployment_info
70 Override of the str method
73 INSTALLER: {installer}
75 INSTALLER IP: {installer_ip}
78 OPENSTACK: {openstack_version} ({openstack_release})
81 '''.format(installer=self.deployment_info['installer'],
82 scenario=self.deployment_info['scenario'],
83 installer_ip=self.deployment_info['installer_ip'],
84 pod=self.deployment_info['pod'],
85 status=self.deployment_info['status'],
86 openstack_version=self.deployment_info[
88 openstack_release=self._get_openstack_release(),
89 sdn_controller=self.deployment_info['sdn_controller'])
91 for node in self.deployment_info['nodes']:
92 s += '{node_object}\n'.format(node_object=node)
98 INSTALLER = 'installer'
99 CONTROLLER = 'controller'
107 STATUS_INACTIVE = 'inactive'
108 STATUS_OFFLINE = 'offline'
109 STATUS_ERROR = 'error'
110 STATUS_UNUSED = 'unused'
127 self.ssh_client = ssh_client
131 self.cpu_info = 'unknown'
132 self.memory = 'unknown'
135 if ssh_client and Role.INSTALLER not in self.roles:
136 sys_info = self.get_system_info()
137 self.cpu_info = sys_info['cpu_info']
138 self.memory = sys_info['memory']
139 self.ovs = self.get_ovs_info()
141 def get_file(self, src, dest):
145 if self.status is not NodeStatus.STATUS_OK:
146 logger.info("The node %s is not active" % self.ip)
148 logger.info("Fetching %s from %s" % (src, self.ip))
149 get_file_result = ssh_utils.get_file(self.ssh_client, src, dest)
150 if get_file_result is None:
151 logger.error("SFTP failed to retrieve the file.")
153 logger.info("Successfully copied %s:%s to %s" %
154 (self.ip, src, dest))
155 return get_file_result
157 def put_file(self, src, dest):
161 if self.status is not NodeStatus.STATUS_OK:
162 logger.info("The node %s is not active" % self.ip)
164 logger.info("Copying %s to %s" % (src, self.ip))
165 put_file_result = ssh_utils.put_file(self.ssh_client, src, dest)
166 if put_file_result is None:
167 logger.error("SFTP failed to retrieve the file.")
169 logger.info("Successfully copied %s to %s:%s" %
170 (src, dest, self.ip))
171 return put_file_result
173 def run_cmd(self, cmd):
175 Run command remotely on a node
177 if self.status is not NodeStatus.STATUS_OK:
179 "Error running command %s. The node %s is not active"
182 _, stdout, stderr = (self.ssh_client.exec_command(cmd))
183 error = stderr.readlines()
185 logger.error("error %s" % ''.join(error))
187 output = ''.join(stdout.readlines()).rstrip()
192 Returns a dictionary with all the attributes
198 'status': self.status,
200 'cpu_info': self.cpu_info,
201 'memory': self.memory,
208 Returns if the node is active
210 if self.status == NodeStatus.STATUS_OK:
214 def is_controller(self):
216 Returns if the node is a controller
218 return Role.CONTROLLER in self.roles
220 def is_compute(self):
222 Returns if the node is a compute
224 return Role.COMPUTE in self.roles
228 Returns if the node is an opendaylight
230 return Role.ODL in self.roles
232 def get_ovs_info(self):
234 Returns the ovs version installed
237 cmd = "ovs-vsctl --version|head -1| sed 's/^.*) //'"
238 return self.run_cmd(cmd)
241 def get_system_info(self):
243 Returns the ovs version installed
245 cmd = 'grep MemTotal /proc/meminfo'
246 memory = self.run_cmd(cmd).partition('MemTotal:')[-1].strip().encode()
250 result = self.run_cmd(cmd)
251 for line in result.splitlines():
252 if line.startswith('CPU(s)'):
253 cpu_info['num_cpus'] = line.split(' ')[-1].encode()
254 elif line.startswith('Thread(s) per core'):
255 cpu_info['threads/core'] = line.split(' ')[-1].encode()
256 elif line.startswith('Core(s) per socket'):
257 cpu_info['cores/socket'] = line.split(' ')[-1].encode()
258 elif line.startswith('Model name'):
259 cpu_info['model'] = line.partition(
260 'Model name:')[-1].strip().encode()
261 elif line.startswith('Architecture'):
262 cpu_info['arch'] = line.split(' ')[-1].encode()
264 return {'memory': memory, 'cpu_info': cpu_info}
276 info: {info}'''.format(name=self.name,
281 cpu_info=self.cpu_info,
287 class DeploymentHandler(object):
290 EX_ERROR = os.EX_SOFTWARE
291 FUNCTION_NOT_IMPLEMENTED = "Function not implemented by adapter!"
300 self.installer = installer.lower()
301 self.installer_ip = installer_ip
302 self.installer_user = installer_user
303 self.installer_pwd = installer_pwd
304 self.pkey_file = pkey_file
306 if pkey_file is not None and not os.path.isfile(pkey_file):
308 'The private key file %s does not exist!' % pkey_file)
310 self.installer_connection = ssh_utils.get_ssh_client(
311 hostname=self.installer_ip,
312 username=self.installer_user,
313 password=self.installer_pwd,
314 pkey_file=self.pkey_file)
316 if self.installer_connection:
317 self.installer_node = Node(id='',
320 status=NodeStatus.STATUS_OK,
321 ssh_client=self.installer_connection,
322 roles=Role.INSTALLER)
325 'Cannot establish connection to the installer node!')
327 self.nodes = self.get_nodes()
330 def get_openstack_version(self):
332 Returns a string of the openstack version (nova-compute)
334 raise Exception(DeploymentHandler.FUNCTION_NOT_IMPLEMENTED)
337 def get_sdn_version(self):
339 Returns a string of the sdn controller and its version, if exists
341 raise Exception(DeploymentHandler.FUNCTION_NOT_IMPLEMENTED)
344 def get_deployment_status(self):
346 Returns a string of the status of the deployment
348 raise Exception(DeploymentHandler.FUNCTION_NOT_IMPLEMENTED)
351 def get_nodes(self, options=None):
353 Generates a list of all the nodes in the deployment
355 raise Exception(DeploymentHandler.FUNCTION_NOT_IMPLEMENTED)
357 def get_installer_node(self):
359 Returns the installer node object
361 return self.installer_node
365 Returns the architecture of the first compute node found
368 for node in self.nodes:
369 if node.is_compute():
370 arch = node.cpu_info.get('arch', None)
375 def get_deployment_info(self):
377 Returns an object of type Deployment
379 return Deployment(installer=self.installer,
380 installer_ip=self.installer_ip,
381 scenario=os.getenv('DEPLOY_SCENARIO', 'Unknown'),
382 status=self.get_deployment_status(),
383 pod=os.getenv('NODE_NAME', 'Unknown'),
384 openstack_version=self.get_openstack_version(),
385 sdn_controller=self.get_sdn_version(),
386 nodes=self.get_nodes())