65
69
def bmc_user_get(user_number, parameter):
66
70
"""Get a user parameter via bmc-config commit."""
67
71
key = format_user_key(user_number, parameter)
73
pattern = r'^\s*%s(?:[ \t])+([^#\s]+[^\n]*)$' % (re.escape(parameter))
74
match = re.search(pattern, raw, re.MULTILINE)
71
80
def bmc_user_set(user_number, parameter, value):
74
83
bmc_set(key, value)
86
def bmc_list_sections():
87
"""Retrieve the names of config sections from the BMC."""
88
command = ('bmc-config', '-L')
89
output = run_command(command)
93
def list_user_numbers():
94
"""List the user numbers on the BMC."""
95
output = bmc_list_sections()
96
pattern = r'^(User\d+)$'
97
users = re.findall(pattern, output, re.MULTILINE)
102
def pick_user_number_from_list(search_username, user_numbers):
103
"""Pick the best user number for a user from a list of user numbers.
105
If any any existing user's username matches the search username, pick
108
Otherwise, pick the first user that has no username set.
110
If no users match those criteria, raise an IPMIError.
114
for user_number in user_numbers:
115
# The IPMI spec reserves User1 as anonymous.
116
if user_number == 'User1':
119
username = bmc_user_get(user_number, 'Username')
121
if username == search_username:
124
# Usually a BMC won't include a Username value if the user is unused.
125
# Some HP BMCs use "(Empty User)" to indicate a user in unused.
126
if username in [None, '(Empty User)'] and first_unused is None:
127
first_unused = user_number
132
def pick_user_number(search_username):
133
"""Pick the best user number for a username."""
134
user_numbers = list_user_numbers()
135
user_number = pick_user_number_from_list(search_username, user_numbers)
138
raise IPMIError('No IPMI user slots available.')
77
143
def is_ipmi_dhcp():
78
144
output = bmc_get('Lan_Conf:IP_Address_Source')
79
145
show_re = re.compile('IP_Address_Source\s+Use_DHCP')
91
157
return res.group()
94
def get_ipmi_user_number(user):
95
for i in range(1, 17):
96
ipmi_user_number = "User%s" % i
97
# bmc-config fails if no slot for the requested user exists;
98
# instead of bailing, just keep trying remaining users.
100
output = bmc_user_get(ipmi_user_number, 'Username')
101
except subprocess.CalledProcessError:
105
return ipmi_user_number
109
def commit_ipmi_user_settings(user, password):
110
ipmi_user_number = get_ipmi_user_number(user)
111
if ipmi_user_number is None:
112
bmc_user_set('User10', 'Username', user)
113
ipmi_user_number = get_ipmi_user_number(user)
114
bmc_user_set(ipmi_user_number, 'Username', user)
115
bmc_user_set(ipmi_user_number, 'Password', password)
116
bmc_user_set(ipmi_user_number, 'Enable_User', 'Yes')
117
bmc_user_set(ipmi_user_number, 'Lan_Enable_IPMI_Msgs', 'Yes')
118
bmc_user_set(ipmi_user_number, 'Lan_Privilege_Limit', 'Administrator')
160
def verify_ipmi_user_settings(user_number, user_settings):
161
"""Verify user settings were applied correctly."""
165
for key, expected_value in user_settings.iteritems():
166
# Password isn't included in checkout.
167
if key == 'Password':
170
actual_value = bmc_user_get(user_number, key)
171
if expected_value != actual_value:
172
bad_values[key] = actual_value
174
if len(bad_values) == 0:
177
errors_string = ' '.join([
178
"for '%s', expected '%s', actual '%s';" % (
179
key, user_settings[key], actual_value)
180
for key, actual_value in bad_values.iteritems()
182
message = 'IPMI user setting verification failures: %s.' % (errors_string)
183
raise IPMIError(message)
186
def apply_ipmi_user_settings(user_settings):
187
"""Commit and verify IPMI user settings."""
188
username = user_settings['Username']
189
ipmi_user_number = pick_user_number(username)
191
for key, value in user_settings.iteritems():
192
bmc_user_set(ipmi_user_number, key, value)
194
verify_ipmi_user_settings(ipmi_user_number, user_settings)
121
197
def commit_ipmi_settings(config):
122
run_command(('bmc-config', '--commit', '--filename %s') % config)
198
run_command(('bmc-config', '--commit', '--filename', config))
125
201
def get_maas_power_settings(user, password, ipaddress, version):
142
218
return ''.join([random.choice(letters) for _ in range(length)])
145
def get_ipmi_version():
221
def bmc_supports_lan2_0():
222
"""Detect if BMC supports LAN 2.0."""
146
223
output = run_command(('ipmi-locate'))
148
#IPMI locate driver: SMBIOS
151
#BMC I/O base address: 0xCA2
153
#show_re = re.compile('(IPMI\ Version:) (\d\.\d)')
154
show_re = re.compile(
155
'(IPMI\ Version:) (\d\.\d)(\n)(.*)(\n)(.*)(\n)(.*)(\n)'
156
'(BMC\ I\/O\ base\ address:) (0xCA2)')
157
res = show_re.search(output)
224
return 'IPMI Version: 2.0' in output
183
247
set_ipmi_network_source("Use_DHCP")
184
248
# allow IPMI 120 seconds to obtain an IP address
187
250
# create user/pass
188
251
IPMI_MAAS_USER = "maas"
189
252
IPMI_MAAS_PASSWORD = generate_random_password()
191
254
# Configure IPMI user/password
192
commit_ipmi_user_settings(IPMI_MAAS_USER, IPMI_MAAS_PASSWORD)
257
'Username': IPMI_MAAS_USER,
258
'Password': IPMI_MAAS_PASSWORD,
259
'Enable_User': 'Yes',
260
'Lan_Enable_IPMI_Msgs': 'Yes',
261
'Lan_Privilege_Limit': 'Administrator'
264
apply_ipmi_user_settings(user_settings)
194
266
# Commit other IPMI settings
195
267
if args.configdir: