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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 from cmdatahandlers.api import configerror
18 from cmdatahandlers.api import config
19 from cmdatahandlers.api import utils
20 from serviceprofiles import profiles
22 VNF_EMBEDDED_RESERVED_MEMORY = "512Mi"
23 DUAL_VIM_CONTROLLER_RESERVED_MEMORY = "64Gi"
24 DUAL_VIM_DEFAULT_RESERVED_MEMORY = "32Gi"
25 MIDDLEWARE_RESERVED_MEMORY = "12Gi"
27 class Config(config.Config):
28 def __init__(self, confman):
29 super(Config, self).__init__(confman)
30 self.ROOT = 'cloud.hosts'
33 self.update_service_profiles()
43 hosts = self.get_hosts()
44 except configerror.ConfigError:
48 utils.validate_list_items_unique(hosts)
51 self._validate_host(host)
53 def mask_sensitive_data(self):
54 for hostname in self.config[self.ROOT].keys():
55 self.config[self.ROOT][hostname]['hwmgmt']['password'] = self.MASK
56 self.config[self.ROOT][hostname]['hwmgmt']['snmpv2_trap_community_string'] = self.MASK
57 self.config[self.ROOT][hostname]['hwmgmt']['snmpv3_authpass'] = self.MASK
58 self.config[self.ROOT][hostname]['hwmgmt']['snmpv3_privpass'] = self.MASK
60 def _validate_host(self, hostname):
61 self._validate_hwmgmt(hostname)
62 self._validate_service_profiles(hostname)
63 self._validate_network_profiles(hostname)
64 self._validate_performance_profiles(hostname)
65 self._validate_storage_profiles(hostname)
67 def _validate_hwmgmt(self, hostname):
68 ip = self.get_hwmgmt_ip(hostname)
69 utils.validate_ipv4_address(ip)
70 self.get_hwmgmt_user(hostname)
71 self.get_hwmgmt_password(hostname)
72 netconf = self.confman.get_networking_config_handler()
76 hwmgmtnet = netconf.get_hwmgmt_network_name()
77 except configerror.ConfigError:
81 domain = self.get_host_network_domain(hostname)
82 cidr = netconf.get_network_cidr(hwmgmtnet, domain)
83 utils.validate_ip_in_network(ip, cidr)
85 def _validate_service_profiles(self, hostname):
86 node_profiles = self.get_service_profiles(hostname)
87 utils.validate_list_items_unique(node_profiles)
88 service_profiles_lib = profiles.Profiles()
89 serviceprofiles = service_profiles_lib.get_service_profiles()
90 for profile in node_profiles:
91 if profile not in serviceprofiles:
92 raise configerror.ConfigError('Invalid service profile %s specified for host %s' % (profile, hostname))
94 def _validate_network_profiles(self, hostname):
95 node_profiles = self.get_network_profiles(hostname)
96 utils.validate_list_items_unique(profiles)
97 netprofconf = self.confman.get_network_profiles_config_handler()
98 netprofiles = netprofconf.get_network_profiles()
99 for profile in node_profiles:
100 if profile not in netprofiles:
101 raise configerror.ConfigError('Invalid network profile %s specified for host %s' % (profile, hostname))
103 def _validate_performance_profiles(self, hostname):
104 node_performance_profiles = []
106 node_performance_profiles = self.get_performance_profiles(hostname)
107 except configerror.ConfigError:
110 if node_performance_profiles:
111 utils.validate_list_items_unique(node_performance_profiles)
112 perfprofconf = self.confman.get_performance_profiles_config_handler()
113 perfprofiles = perfprofconf.get_performance_profiles()
114 for profile in node_performance_profiles:
115 if profile not in perfprofiles:
116 raise configerror.ConfigError('Invalid performance profile %s specified for host %s' % (profile, hostname))
118 def _validate_storage_profiles(self, hostname):
119 node_storage_profiles = []
121 node_storage_profiles = self.get_storage_profiles(hostname)
122 except configerror.ConfigError:
125 if node_storage_profiles:
126 utils.validate_list_items_unique(node_storage_profiles)
127 storageprofconf = self.confman.get_storage_profiles_config_handler()
128 storageprofiles = storageprofconf.get_storage_profiles()
129 for profile in node_storage_profiles:
130 if profile not in storageprofiles:
131 raise configerror.ConfigError('Invalid storage profile %s specific for %s' % (profile, hostname))
134 """ get the list of hosts in the cloud
138 A sorted list of host names
142 ConfigError in-case of an error
146 return sorted(self.config[self.ROOT].keys())
148 def get_labels(self, hostname):
149 noderole_label = "node-role.kubernetes.io/{}".format(self.get_noderole(hostname))
151 {"nodetype": self.get_nodetype(hostname),
152 "nodeindex": self.get_nodeindex(hostname),
153 "nodename": self.get_nodename(hostname),
155 labels = self.config[self.ROOT][hostname].get('labels', {}).copy()
156 labels.update(mandatory_labels)
158 if self.is_sriov_enabled(hostname):
159 labels.update({"sriov": "enabled"})
161 black_list = ['name']
162 return {name: attributes
163 for name, attributes in labels.iteritems()
164 if name not in black_list}
166 def get_nodetype(self, hostname):
167 service_profiles_lib = profiles.Profiles()
168 service_profiles = self.get_service_profiles(hostname)
170 if service_profiles_lib.get_caasmaster_service_profile() in service_profiles:
171 return service_profiles_lib.get_caasmaster_service_profile()
172 if service_profiles_lib.get_caasworker_service_profile() in service_profiles:
173 return service_profiles_lib.get_caasworker_service_profile()
175 return service_profiles[0]
177 def get_nodeindex(self, hostname):
178 return re.search(r'[-_](\d+)$', hostname).group(1)
180 def get_nodename(self, hostname):
181 return "{}{}".format(self.get_nodetype(hostname), self.get_nodeindex(hostname))
183 def get_noderole(self, hostname):
184 service_profiles_lib = profiles.Profiles()
185 service_profiles = self.get_service_profiles(hostname)
187 if service_profiles_lib.get_caasmaster_service_profile() in service_profiles:
191 def is_sriov_enabled(self, hostname):
192 netprofs = self.get_network_profiles(hostname)
193 netprofconf = self.confman.get_network_profiles_config_handler()
194 for netprof in netprofs:
195 if 'sriov_provider_networks' in self.config[netprofconf.ROOT][netprof]:
199 def get_enabled_hosts(self):
200 """ get the list of enabled hosts in the cloud
208 ConfigError in-case of an error
211 hosts = self.get_hosts()
214 if self.is_host_enabled(host):
218 def get_hwmgmt_ip(self, hostname):
219 """get the hwmgmt ip address
223 hostname: The name of the node
227 The BMC ip address as a string
231 ConfigError in-case of an error
233 self._validate_hostname(hostname)
235 if 'hwmgmt' not in self.config[self.ROOT][hostname] or 'address' not in self.config[self.ROOT][hostname]['hwmgmt']:
236 raise configerror.ConfigError('No hwmgmt info defined for host')
238 return self.config[self.ROOT][hostname]['hwmgmt']['address']
240 def get_hwmgmt_user(self, hostname):
241 """get the hwmgmt user
245 hostname: The name of the node
253 ConfigError in-case of an error
255 self._validate_hostname(hostname)
257 if 'hwmgmt' not in self.config[self.ROOT][hostname] or 'user' not in self.config[self.ROOT][hostname]['hwmgmt']:
258 raise configerror.ConfigError('No hwmgmt info defined for host')
260 return self.config[self.ROOT][hostname]['hwmgmt']['user']
262 def get_hwmgmt_password(self, hostname):
263 """get the hwmgmt password
267 hostname: The name of the node
275 ConfigError in-case of an error
277 self._validate_hostname(hostname)
279 if 'hwmgmt' not in self.config[self.ROOT][hostname] or 'password' not in self.config[self.ROOT][hostname]['hwmgmt']:
280 raise configerror.ConfigError('No hwmgmt info defined for host')
282 return self.config[self.ROOT][hostname]['hwmgmt']['password']
284 def get_service_profiles(self, hostname):
285 """get the node service profiles
289 hostname: The name of the node
293 A list containing service profile names
297 ConfigError in-case of an error
299 self._validate_hostname(hostname)
301 if 'service_profiles' not in self.config[self.ROOT][hostname]:
302 raise configerror.ConfigError('No service profiles found')
304 return self.config[self.ROOT][hostname]['service_profiles']
306 def get_performance_profiles(self, hostname):
307 """ get the performance profiles
311 hostname: The name of the node
315 A list containing the perfromance profile names.
319 ConfigError in-case of an error
321 self._validate_hostname(hostname)
323 if 'performance_profiles' not in self.config[self.ROOT][hostname]:
324 raise configerror.ConfigError('No performance profiles found')
326 return self.config[self.ROOT][hostname]['performance_profiles']
328 def get_network_profiles(self, hostname):
329 """get the node network profiles
333 hostname: The name of the node
337 A list containing network profile names
341 ConfigError in-case of an error
343 self._validate_hostname(hostname)
345 if 'network_profiles' not in self.config[self.ROOT][hostname]:
346 raise configerror.ConfigError('No network profiles found')
348 return self.config[self.ROOT][hostname]['network_profiles']
350 def get_storage_profiles(self, hostname):
351 """get the node storage profiles
355 hostname: The name of the node
359 A list containing storage profile names
363 ConfigError in-case of an error
365 self._validate_hostname(hostname)
367 if 'storage_profiles' not in self.config[self.ROOT][hostname]:
368 raise configerror.ConfigError('No storage profiles found')
370 return self.config[self.ROOT][hostname]['storage_profiles']
372 def _validate_hostname(self, hostname):
373 if not self.is_valid_host(hostname):
374 raise configerror.ConfigError('Invalid hostname given %s' % hostname)
376 def is_valid_host(self, hostname):
377 """check if a host is valid
381 hostname: The name of the node
389 ConfigError in-case of an error
392 if hostname in self.config[self.ROOT]:
396 def get_service_profile_hosts(self, profile):
397 """ get hosts having some service profile
409 ConfigError in-case of an error
411 hosts = self.get_hosts()
414 node_profiles = self.get_service_profiles(host)
415 if profile in node_profiles:
420 def get_network_profile_hosts(self, profile):
421 """ get hosts having some network profile
433 ConfigError in-case of an error
435 hosts = self.get_hosts()
438 node_network_profiles = self.get_network_profiles(host)
439 if profile in node_network_profiles:
442 raise configerror.ConfigError('No hosts found for profile %s' % profile)
446 def get_performance_profile_hosts(self, profile):
447 """ get hosts having some performance profile
451 performance profile name
459 ConfigError in-case of an error
461 hosts = self.get_hosts()
464 node_performance_profiles = self.get_performance_profiles(host)
465 if profile in node_performance_profiles:
468 raise configerror.ConfigError('No hosts found for profile %s' % profile)
472 def get_storage_profile_hosts(self, profile):
473 """ get hosts having some storage profile
485 ConfigError in-case of an error
487 hosts = self.get_hosts()
491 node_storage_profiles = self.get_storage_profiles(host)
492 if profile in node_storage_profiles:
494 except configerror.ConfigError:
498 raise configerror.ConfigError('No hosts found for profile %s' % profile)
502 def get_host_network_interface(self, host, network):
503 """ get the host interface used for some network
517 ConfigError in-case of an error
519 node_network_profiles = self.get_network_profiles(host)
520 netprofconf = self.confman.get_network_profiles_config_handler()
521 for profile in node_network_profiles:
522 interfaces = netprofconf.get_profile_network_mapped_interfaces(profile)
523 for interface in interfaces:
524 networks = netprofconf.get_profile_interface_mapped_networks(profile, interface)
525 if network in networks:
528 raise configerror.ConfigError('No interfaces found for network %s in host %s' % (network, host))
530 def get_host_network_ip_holding_interface(self, host, network):
531 """ get the host ip holding interface some network
545 ConfigError in-case of an error
547 networkingconf = self.confman.get_networking_config_handler()
550 domain = self.get_host_network_domain(host)
551 vlan = networkingconf.get_network_vlan_id(network, domain)
552 except configerror.ConfigError as exp:
556 return 'vlan'+str(vlan)
558 return self.get_host_network_interface(host, network)
560 def get_host_networks(self, hostname):
561 """ get the host networks
569 A list of network names
573 ConfigError in-case of an error
575 node_network_profiles = self.get_network_profiles(hostname)
576 netprofconf = self.confman.get_network_profiles_config_handler()
578 for profile in node_network_profiles:
579 interfaces = netprofconf.get_profile_network_mapped_interfaces(profile)
580 for interface in interfaces:
581 networks = netprofconf.get_profile_interface_mapped_networks(profile, interface)
582 for network in networks:
583 if network not in result:
584 result.append(network)
586 raise configerror.ConfigError('No networks found for host %s' % hostname)
590 def get_host_having_hwmgmt_address(self, hwmgmtips):
591 """ get the node name matching an ipmi address
603 ConfigError in-case of an error
606 hosts = self.get_hosts()
608 ip = self.get_hwmgmt_ip(host)
609 for hwmgtip in hwmgmtips:
610 addr=ipaddress.ip_address(unicode(hwmgtip))
611 if addr.version == 6:
612 hwmgtip=addr.compressed
613 ip=ipaddress.ip_address(unicode(ip))
617 raise configerror.ConfigError('No hosts are matching the provided hw address %s' % hwmgmtips)
619 def set_installation_host(self, name):
620 """ set the installation node
624 The installation node name
628 ConfigError in-case of an error
630 self._validate_hostname(name)
632 self.config[self.ROOT][name]['installation_host'] = True
634 def is_installation_host(self, name):
635 """ get if the node is an installation node
643 True if installation node
647 ConfigError in-case of an error
649 self._validate_hostname(name)
651 if 'installation_host' in self.config[self.ROOT][name]:
652 return self.config[self.ROOT][name]['installation_host']
656 def get_installation_host(self):
657 """ get the name of the node used for installation
665 ConfigError in-case of an error
667 hosts = self.get_hosts()
669 if self.is_installation_host(host):
672 raise configerror.ConfigError('No installation host found')
674 def disable_host(self, host):
675 """ disable the hosts visible via configuration.
676 This can be used in bootstrapping phase.
684 ConfigError in-case if provided host is not valid
686 self._validate_hostname(host)
688 self.config[self.ROOT][host]['disabled'] = True
690 def enable_host(self, host):
691 """ enable the hosts visible via configuration.
692 This can be used in bootstrapping phase.
700 ConfigError in-case if provided host is not valid
702 self._validate_hostname(host)
704 self.config[self.ROOT][host]['disabled'] = False
706 def is_host_enabled(self, host):
707 """ is the host enabled
711 the host to be checked
715 ConfigError in-case if provided host is not valid
717 self._validate_hostname(host)
719 if 'disabled' in self.config[self.ROOT][host]:
720 return not self.config[self.ROOT][host]['disabled']
724 def get_mgmt_mac(self, host):
725 self._validate_hostname(host)
727 if 'mgmt_mac' in self.config[self.ROOT][host]:
728 return self.config[self.ROOT][host]['mgmt_mac']
731 def get_host_network_domain(self, host):
732 self._validate_hostname(host)
733 if 'network_domain' not in self.config[self.ROOT][host]:
734 raise configerror.ConfigError('Missing network domain for host %s' % host)
735 return self.config[self.ROOT][host]['network_domain']
737 def get_controllers_network_domain(self):
738 controllers = self.get_service_profile_hosts('controller')
740 for controller in controllers:
741 domains.add(self.get_host_network_domain(controller))
743 if len(domains) != 1:
744 raise configerror.ConfigError('Controllers in different networking domains not supported')
747 def get_managements_network_domain(self):
748 managements = self.get_service_profile_hosts('management')
750 for management in managements:
751 domains.add(self.get_host_network_domain(management))
752 if len(domains) != 1:
753 raise configerror.ConfigError('Management in different networking domains not supported')
756 def update_service_profiles(self):
757 profs = profiles.Profiles()
758 hosts = self.get_hosts()
761 current_profiles = self.config[self.ROOT][host]['service_profiles']
762 new_profiles = current_profiles
763 for profile in current_profiles:
764 included_profiles = profs.get_included_profiles(profile)
765 new_profiles = utils.add_lists(new_profiles, included_profiles)
766 self.config[self.ROOT][host]['service_profiles'] = new_profiles
768 def get_pre_allocated_ips(self, host, network):
769 ips_field = "pre_allocated_ips"
770 self._validate_hostname(host)
771 if (ips_field not in self.config[self.ROOT][host]
772 or network not in self.config[self.ROOT][host][ips_field]):
774 return self.config[self.ROOT][host][ips_field][network]
776 def allocate_port(self, host, base, name):
778 hosts = self.get_hosts()
780 if name in self.config[self.ROOT][node]:
781 used_ports.append(self.config[self.ROOT][node][name])
785 for port in range(base, base+1000):
786 if port not in used_ports:
791 raise configerror.ConfigError('No free ports available')
793 self.config[self.ROOT][host][name] = free_port
795 def add_vbmc_port(self, host):
796 base_vbmc_port = 61600
798 self._validate_hostname(host)
799 if name not in self.config[self.ROOT][host]:
800 self.allocate_port(host, base_vbmc_port, name)
802 def add_ipmi_terminal_port(self, host):
803 base_console_port = 61401
804 name = 'ipmi_terminal_port'
805 self._validate_hostname(host)
806 if name not in self.config[self.ROOT][host]:
807 self.allocate_port(host, base_console_port, name)
809 def get_ceph_osd_disks(self, host):
810 self._validate_hostname(host)
811 caas_disks = self.config[self.ROOT][host].get('caas_disks', [])
812 osd_disks = filter(lambda disk: disk.get('osd_disk', False), caas_disks)
813 return map(lambda disk: _get_path_for_virtio_id(disk), osd_disks)
815 def get_system_reserved_memory(self, hostname):
816 caasconf = self.confman.get_caas_config_handler()
817 if caasconf.is_vnf_embedded_deployment():
818 return VNF_EMBEDDED_RESERVED_MEMORY
820 profiles = self.get_service_profiles(hostname)
821 if 'controller' in profiles:
822 return DUAL_VIM_CONTROLLER_RESERVED_MEMORY
823 if 'compute' in profiles:
824 return DUAL_VIM_DEFAULT_RESERVED_MEMORY
826 return self.config.get(self.ROOT, {}).get('middleware_reserved_memory',
827 MIDDLEWARE_RESERVED_MEMORY)
829 def set_default_reserved_memory_to_all_hosts(self, def_memory):
830 for host in self.get_hosts():
831 self.config[self.ROOT][host]['middleware_reserved_memory'] = def_memory
834 def _get_path_for_virtio_id(disk):
835 disk_id = disk.get('id', '')
837 return "/dev/disk/by-id/virtio-{}".format(disk_id[:20])