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 get_hwmgmt_priv_level(self, hostname):
86 """get the hwmgmt IPMI privilege level. Defaults to ADMINISTRATOR
90 hostname: The name of the node
94 The prvilege level, or ADMINISTRATOR if unspecified
98 ConfigError in-case of an error
100 self._validate_hostname(hostname)
102 if 'hwmgmt' not in self.config[self.ROOT][hostname]:
103 raise configerror.ConfigError('No hwmgmt info defined for host')
105 return self.config[self.ROOT][hostname]['hwmgmt'].get('priv_level', 'ADMINISTRATOR')
107 def _validate_service_profiles(self, hostname):
108 node_profiles = self.get_service_profiles(hostname)
109 utils.validate_list_items_unique(node_profiles)
110 service_profiles_lib = profiles.Profiles()
111 serviceprofiles = service_profiles_lib.get_service_profiles()
112 for profile in node_profiles:
113 if profile not in serviceprofiles:
114 raise configerror.ConfigError('Invalid service profile %s specified for host %s' % (profile, hostname))
116 def _validate_network_profiles(self, hostname):
117 node_profiles = self.get_network_profiles(hostname)
118 utils.validate_list_items_unique(profiles)
119 netprofconf = self.confman.get_network_profiles_config_handler()
120 netprofiles = netprofconf.get_network_profiles()
121 for profile in node_profiles:
122 if profile not in netprofiles:
123 raise configerror.ConfigError('Invalid network profile %s specified for host %s' % (profile, hostname))
125 def _validate_performance_profiles(self, hostname):
126 node_performance_profiles = []
128 node_performance_profiles = self.get_performance_profiles(hostname)
129 except configerror.ConfigError:
132 if node_performance_profiles:
133 utils.validate_list_items_unique(node_performance_profiles)
134 perfprofconf = self.confman.get_performance_profiles_config_handler()
135 perfprofiles = perfprofconf.get_performance_profiles()
136 for profile in node_performance_profiles:
137 if profile not in perfprofiles:
138 raise configerror.ConfigError('Invalid performance profile %s specified for host %s' % (profile, hostname))
140 def _validate_storage_profiles(self, hostname):
141 node_storage_profiles = []
143 node_storage_profiles = self.get_storage_profiles(hostname)
144 except configerror.ConfigError:
147 if node_storage_profiles:
148 utils.validate_list_items_unique(node_storage_profiles)
149 storageprofconf = self.confman.get_storage_profiles_config_handler()
150 storageprofiles = storageprofconf.get_storage_profiles()
151 for profile in node_storage_profiles:
152 if profile not in storageprofiles:
153 raise configerror.ConfigError('Invalid storage profile %s specific for %s' % (profile, hostname))
156 """ get the list of hosts in the cloud
160 A sorted list of host names
164 ConfigError in-case of an error
168 return sorted(self.config[self.ROOT].keys())
170 def get_labels(self, hostname):
172 {"nodetype": self.get_nodetype(hostname),
173 "nodeindex": self.get_nodeindex(hostname),
174 "nodename": self.get_nodename(hostname)}
175 labels = self.config[self.ROOT][hostname].get('labels', {}).copy()
176 labels.update(mandatory_labels)
178 if self.is_sriov_enabled(hostname):
179 labels.update({"sriov": "enabled"})
181 if self.is_localstorage_used(hostname):
182 labels.update({"localstorage": "enabled"})
184 black_list = ['name']
185 return {name: attributes
186 for name, attributes in labels.iteritems()
187 if name not in black_list}
189 def get_nodetype(self, hostname):
190 service_profiles_lib = profiles.Profiles()
191 service_profiles = self.get_service_profiles(hostname)
193 if service_profiles_lib.get_caasmaster_service_profile() in service_profiles:
194 return service_profiles_lib.get_caasmaster_service_profile()
195 if service_profiles_lib.get_caasworker_service_profile() in service_profiles:
196 return service_profiles_lib.get_caasworker_service_profile()
198 return service_profiles[0]
200 def set_noderole(self):
201 hosts = self.get_hosts()
203 self.config[self.ROOT][host]['noderole'] = self.get_noderole(host)
205 def set_nodeindex(self):
206 hostsconf = self.confman.get_hosts_config_handler()
207 install_host = utils.get_installation_host_name(hostsconf)
208 self.config[self.ROOT][install_host]['caas_nodeindex'] = 1
210 masters = self.get_service_profile_hosts('caas_master')
211 masters.remove(install_host)
212 self._set_nodeindexes(masters, 2)
213 self._set_nodeindexes(self.get_service_profile_hosts('caas_worker'), 1)
215 def _set_nodeindexes(self, hosts, base_index):
218 self.config[self.ROOT][host]['caas_nodeindex'] = index
221 def get_nodeindex(self, hostname):
222 return self.config[self.ROOT][hostname]['caas_nodeindex']
224 def get_nodename(self, hostname):
225 return "{}{}".format(self.get_nodetype(hostname), self.get_nodeindex(hostname))
227 def get_noderole(self, hostname):
228 service_profiles_lib = profiles.Profiles()
229 service_profiles = self.get_service_profiles(hostname)
231 if service_profiles_lib.get_caasmaster_service_profile() in service_profiles:
235 def is_sriov_enabled(self, hostname):
236 netprofs = self.get_network_profiles(hostname)
237 netprofconf = self.confman.get_network_profiles_config_handler()
238 for netprof in netprofs:
239 if 'sriov_provider_networks' in self.config[netprofconf.ROOT][netprof]:
243 def is_localstorage_used(self, hostname):
244 storageprofs = self.get_storage_profiles(hostname)
245 storageprofconf = self.confman.get_storage_profiles_config_handler()
246 for profile in storageprofs:
247 if "shared" in self.config[storageprofconf.ROOT][profile]:
248 for volume in self.config[storageprofconf.ROOT][profile]["shared"]["volumes"]:
249 if volume["name"] == 'caas_app':
253 def get_enabled_hosts(self):
254 """ get the list of enabled hosts in the cloud
262 ConfigError in-case of an error
265 hosts = self.get_hosts()
268 if self.is_host_enabled(host):
272 def get_hwmgmt_ip(self, hostname):
273 """get the hwmgmt ip address
277 hostname: The name of the node
281 The BMC ip address as a string
285 ConfigError in-case of an error
287 self._validate_hostname(hostname)
289 if 'hwmgmt' not in self.config[self.ROOT][hostname] or 'address' not in self.config[self.ROOT][hostname]['hwmgmt']:
290 raise configerror.ConfigError('No hwmgmt info defined for host')
292 return self.config[self.ROOT][hostname]['hwmgmt']['address']
294 def get_hwmgmt_user(self, hostname):
295 """get the hwmgmt user
299 hostname: The name of the node
307 ConfigError in-case of an error
309 self._validate_hostname(hostname)
311 if 'hwmgmt' not in self.config[self.ROOT][hostname] or 'user' not in self.config[self.ROOT][hostname]['hwmgmt']:
312 raise configerror.ConfigError('No hwmgmt info defined for host')
314 return self.config[self.ROOT][hostname]['hwmgmt']['user']
316 def get_hwmgmt_password(self, hostname):
317 """get the hwmgmt password
321 hostname: The name of the node
329 ConfigError in-case of an error
331 self._validate_hostname(hostname)
333 if 'hwmgmt' not in self.config[self.ROOT][hostname] or 'password' not in self.config[self.ROOT][hostname]['hwmgmt']:
334 raise configerror.ConfigError('No hwmgmt info defined for host')
336 return self.config[self.ROOT][hostname]['hwmgmt']['password']
338 def get_service_profiles(self, hostname):
339 """get the node service profiles
343 hostname: The name of the node
347 A list containing service profile names
351 ConfigError in-case of an error
353 self._validate_hostname(hostname)
355 if 'service_profiles' not in self.config[self.ROOT][hostname]:
356 raise configerror.ConfigError('No service profiles found')
358 return self.config[self.ROOT][hostname]['service_profiles']
360 def get_performance_profiles(self, hostname):
361 """ get the performance profiles
365 hostname: The name of the node
369 A list containing the perfromance profile names.
373 ConfigError in-case of an error
375 self._validate_hostname(hostname)
377 if 'performance_profiles' not in self.config[self.ROOT][hostname]:
378 raise configerror.ConfigError('No performance profiles found')
380 return self.config[self.ROOT][hostname]['performance_profiles']
382 def get_network_profiles(self, hostname):
383 """get the node network profiles
387 hostname: The name of the node
391 A list containing network profile names
395 ConfigError in-case of an error
397 self._validate_hostname(hostname)
399 if 'network_profiles' not in self.config[self.ROOT][hostname]:
400 raise configerror.ConfigError('No network profiles found')
402 return self.config[self.ROOT][hostname]['network_profiles']
404 def get_storage_profiles(self, hostname):
405 """get the node storage profiles
409 hostname: The name of the node
413 A list containing storage profile names
417 ConfigError in-case of an error
419 self._validate_hostname(hostname)
421 if 'storage_profiles' not in self.config[self.ROOT][hostname]:
422 raise configerror.ConfigError('No storage profiles found')
424 return self.config[self.ROOT][hostname]['storage_profiles']
426 def _validate_hostname(self, hostname):
427 if not self.is_valid_host(hostname):
428 raise configerror.ConfigError('Invalid hostname given %s' % hostname)
430 def is_valid_host(self, hostname):
431 """check if a host is valid
435 hostname: The name of the node
443 ConfigError in-case of an error
446 if hostname in self.config[self.ROOT]:
450 def get_service_profile_hosts(self, profile):
451 """ get hosts having some service profile
463 ConfigError in-case of an error
465 hosts = self.get_hosts()
468 node_profiles = self.get_service_profiles(host)
469 if profile in node_profiles:
474 def get_network_profile_hosts(self, profile):
475 """ get hosts having some network profile
487 ConfigError in-case of an error
489 hosts = self.get_hosts()
492 node_network_profiles = self.get_network_profiles(host)
493 if profile in node_network_profiles:
496 raise configerror.ConfigError('No hosts found for profile %s' % profile)
500 def get_performance_profile_hosts(self, profile):
501 """ get hosts having some performance profile
505 performance profile name
513 ConfigError in-case of an error
515 hosts = self.get_hosts()
518 node_performance_profiles = self.get_performance_profiles(host)
519 if profile in node_performance_profiles:
522 raise configerror.ConfigError('No hosts found for profile %s' % profile)
526 def get_storage_profile_hosts(self, profile):
527 """ get hosts having some storage profile
539 ConfigError in-case of an error
541 hosts = self.get_hosts()
545 node_storage_profiles = self.get_storage_profiles(host)
546 if profile in node_storage_profiles:
548 except configerror.ConfigError:
552 raise configerror.ConfigError('No hosts found for profile %s' % profile)
556 def get_host_network_interface(self, host, network):
557 """ get the host interface used for some network
571 ConfigError in-case of an error
573 node_network_profiles = self.get_network_profiles(host)
574 netprofconf = self.confman.get_network_profiles_config_handler()
575 for profile in node_network_profiles:
576 interfaces = netprofconf.get_profile_network_mapped_interfaces(profile)
577 for interface in interfaces:
578 networks = netprofconf.get_profile_interface_mapped_networks(profile, interface)
579 if network in networks:
582 raise configerror.ConfigError('No interfaces found for network %s in host %s' % (network, host))
584 def get_host_network_ip_holding_interface(self, host, network):
585 """ get the host ip holding interface some network
599 ConfigError in-case of an error
601 networkingconf = self.confman.get_networking_config_handler()
604 domain = self.get_host_network_domain(host)
605 vlan = networkingconf.get_network_vlan_id(network, domain)
606 except configerror.ConfigError as exp:
610 return 'vlan'+str(vlan)
612 return self.get_host_network_interface(host, network)
614 def get_host_networks(self, hostname):
615 """ get the host networks
623 A list of network names
627 ConfigError in-case of an error
629 node_network_profiles = self.get_network_profiles(hostname)
630 netprofconf = self.confman.get_network_profiles_config_handler()
632 for profile in node_network_profiles:
633 interfaces = netprofconf.get_profile_network_mapped_interfaces(profile)
634 for interface in interfaces:
635 networks = netprofconf.get_profile_interface_mapped_networks(profile, interface)
636 for network in networks:
637 if network not in result:
638 result.append(network)
640 raise configerror.ConfigError('No networks found for host %s' % hostname)
644 def get_host_having_hwmgmt_address(self, hwmgmtips):
645 """ get the node name matching an ipmi address
657 ConfigError in-case of an error
660 hosts = self.get_hosts()
662 ip = self.get_hwmgmt_ip(host)
663 for hwmgtip in hwmgmtips:
664 addr=ipaddress.ip_address(unicode(hwmgtip))
665 if addr.version == 6:
666 hwmgtip=addr.compressed
667 ip=ipaddress.ip_address(unicode(ip))
671 raise configerror.ConfigError('No hosts are matching the provided hw address %s' % hwmgmtips)
673 def set_installation_host(self, name):
674 """ set the installation node
678 The installation node name
682 ConfigError in-case of an error
684 self._validate_hostname(name)
686 self.config[self.ROOT][name]['installation_host'] = True
688 def is_installation_host(self, name):
689 """ get if the node is an installation node
697 True if installation node
701 ConfigError in-case of an error
703 self._validate_hostname(name)
705 if 'installation_host' in self.config[self.ROOT][name]:
706 return self.config[self.ROOT][name]['installation_host']
710 def get_installation_host(self):
711 """ get the name of the node used for installation
719 ConfigError in-case of an error
721 hosts = self.get_hosts()
723 if self.is_installation_host(host):
726 raise configerror.ConfigError('No installation host found')
728 def disable_host(self, host):
729 """ disable the hosts visible via configuration.
730 This can be used in bootstrapping phase.
738 ConfigError in-case if provided host is not valid
740 self._validate_hostname(host)
742 self.config[self.ROOT][host]['disabled'] = True
744 def enable_host(self, host):
745 """ enable the hosts visible via configuration.
746 This can be used in bootstrapping phase.
754 ConfigError in-case if provided host is not valid
756 self._validate_hostname(host)
758 self.config[self.ROOT][host]['disabled'] = False
760 def is_host_enabled(self, host):
761 """ is the host enabled
765 the host to be checked
769 ConfigError in-case if provided host is not valid
771 self._validate_hostname(host)
773 if 'disabled' in self.config[self.ROOT][host]:
774 return not self.config[self.ROOT][host]['disabled']
778 def get_mgmt_mac(self, host):
779 self._validate_hostname(host)
781 if 'mgmt_mac' in self.config[self.ROOT][host]:
782 return self.config[self.ROOT][host]['mgmt_mac']
785 def get_host_network_domain(self, host):
786 self._validate_hostname(host)
787 if 'network_domain' not in self.config[self.ROOT][host]:
788 raise configerror.ConfigError('Missing network domain for host %s' % host)
789 return self.config[self.ROOT][host]['network_domain']
791 def get_controllers_network_domain(self):
792 controllers = self.get_service_profile_hosts('controller')
794 for controller in controllers:
795 domains.add(self.get_host_network_domain(controller))
797 if len(domains) != 1:
798 raise configerror.ConfigError('Controllers in different networking domains not supported')
801 def get_managements_network_domain(self):
802 managements = self.get_service_profile_hosts('management')
804 for management in managements:
805 domains.add(self.get_host_network_domain(management))
806 if len(domains) != 1:
807 raise configerror.ConfigError('Management in different networking domains not supported')
810 def update_service_profiles(self):
811 profs = profiles.Profiles()
812 hosts = self.get_hosts()
815 current_profiles = self.config[self.ROOT][host]['service_profiles']
816 new_profiles = current_profiles
817 for profile in current_profiles:
818 included_profiles = profs.get_included_profiles(profile)
819 new_profiles = utils.add_lists(new_profiles, included_profiles)
820 self.config[self.ROOT][host]['service_profiles'] = new_profiles
822 def get_pre_allocated_ips(self, host, network):
823 ips_field = "pre_allocated_ips"
824 self._validate_hostname(host)
825 if (ips_field not in self.config[self.ROOT][host]
826 or network not in self.config[self.ROOT][host][ips_field]):
828 return self.config[self.ROOT][host][ips_field][network]
830 def allocate_port(self, host, base, name):
832 hosts = self.get_hosts()
834 if name in self.config[self.ROOT][node]:
835 used_ports.append(self.config[self.ROOT][node][name])
839 for port in range(base, base+1000):
840 if port not in used_ports:
845 raise configerror.ConfigError('No free ports available')
847 self.config[self.ROOT][host][name] = free_port
849 def add_vbmc_port(self, host):
850 base_vbmc_port = 61600
852 self._validate_hostname(host)
853 if name not in self.config[self.ROOT][host]:
854 self.allocate_port(host, base_vbmc_port, name)
856 def add_ipmi_terminal_port(self, host):
857 base_console_port = 61401
858 name = 'ipmi_terminal_port'
859 self._validate_hostname(host)
860 if name not in self.config[self.ROOT][host]:
861 self.allocate_port(host, base_console_port, name)
863 def get_ceph_osd_disks(self, host):
864 self._validate_hostname(host)
865 caas_disks = self.config[self.ROOT][host].get('caas_disks', [])
866 osd_disks = filter(lambda disk: disk.get('osd_disk', False), caas_disks)
867 return map(lambda disk: _get_path_for_virtio_id(disk), osd_disks)
869 def get_system_reserved_memory(self, hostname):
870 caasconf = self.confman.get_caas_config_handler()
871 if caasconf.is_vnf_embedded_deployment():
872 return VNF_EMBEDDED_RESERVED_MEMORY
874 profiles = self.get_service_profiles(hostname)
875 if 'controller' in profiles:
876 return DUAL_VIM_CONTROLLER_RESERVED_MEMORY
877 if 'compute' in profiles:
878 return DUAL_VIM_DEFAULT_RESERVED_MEMORY
880 return self.config.get(self.ROOT, {}).get('middleware_reserved_memory',
881 MIDDLEWARE_RESERVED_MEMORY)
883 def set_default_reserved_memory_to_all_hosts(self, def_memory):
884 for host in self.get_hosts():
885 self.config[self.ROOT][host]['middleware_reserved_memory'] = def_memory
887 def set_default_ipmi_priv_level_to_all_hosts(self, def_priv):
888 for host in self.get_hosts():
889 if 'hwmgmt' not in self.config[self.ROOT][host]:
890 self.config[self.ROOT][host]['hwmgmt'] = {'priv_level': def_priv}
891 elif 'priv_level' not in self.config[self.ROOT][host]['hwmgmt']:
892 self.config[self.ROOT][host]['hwmgmt']['priv_level'] = def_priv
895 def _get_path_for_virtio_id(disk):
896 disk_id = disk.get('id', '')
898 return "/dev/disk/by-id/virtio-{}".format(disk_id[:20])