def process(self, data): """Process the given data received from the cloud-config userdata. It knows to process only lists and dicts. """ if not isinstance(data, (list, dict)): raise exception.CloudbaseInitException( "Can't process the type of data %r" % type(data)) osutils = osutils_factory.get_os_utils() for item in data: group_name = None group_users = [] if isinstance(item, six.string_types): group_name = item elif isinstance(item, dict): try: group_name = list(item.keys())[0] group_users = item.get(group_name, []) except Exception: LOG.error("Group details could not be parsed") raise else: raise exception.CloudbaseInitException( "Unrecognized type '%r' in group definition" % type(item)) if not group_name: LOG.warning("Group name cannot be empty") continue try: if not osutils.group_exists(group_name): osutils.create_group(group_name) else: LOG.warning("Group '%s' already exists" % group_name) for group_user in group_users: osutils.add_user_to_local_group(group_user, group_name) except Exception as exc: raise exception.CloudbaseInitException( "Group '%s' could not be configured. Exception code: %s" % (group_name, exc)) return False
def seek(self, offset): high = wintypes.DWORD(offset >> 32) low = wintypes.DWORD(offset & 0xFFFFFFFF) ret_val = kernel32.SetFilePointer(self._handle, low, ctypes.byref(high), self.FILE_BEGIN) if ret_val == self.INVALID_SET_FILE_POINTER: raise exception.CloudbaseInitException("Seek error")
def set_service_start_mode(self, service_name, start_mode): # TODO(alexpilotti): Handle the "Delayed Start" case service = self._get_service(service_name) (ret_val,) = service.ChangeStartMode(start_mode) if ret_val != 0: raise exception.CloudbaseInitException( 'Setting service %(service_name)s start mode failed with ' 'return value: %(ret_val)d' % {'service_name': service_name, 'ret_val': ret_val})
def stop_service(self, service_name): LOG.debug('Stopping service %s', service_name) service = self._get_service(service_name) (ret_val,) = service.StopService() if ret_val != 0: raise exception.CloudbaseInitException( 'Stopping service %(service_name)s failed with return value:' ' %(ret_val)d' % {'service_name': service_name, 'ret_val': ret_val})
def set_current_bcd_device_to_boot_partition(): current_store = _get_current_bcd_store() success, = current_store.SetDeviceElement(Type=BCDOSLOADER_DEVICE_OSDEVICE, DeviceType=BOOT_DEVICE, AdditionalOptions="") if not success: raise exception.CloudbaseInitException( "Cannot set device element: %s" % BCDOSLOADER_DEVICE_OSDEVICE) success, = current_store.SetDeviceElement( Type=BCDLIBRARY_DEVICE_APPLICATION_DEVICE, DeviceType=BOOT_DEVICE, AdditionalOptions="") if not success: raise exception.CloudbaseInitException( "Cannot set device element: %s" % BCDLIBRARY_DEVICE_APPLICATION_DEVICE)
def _get_logical_drives(self): buf_size = self.MAX_PATH buf = ctypes.create_unicode_buffer(buf_size + 1) buf_len = kernel32.GetLogicalDriveStringsW(buf_size, buf) if not buf_len: raise exception.CloudbaseInitException( "GetLogicalDriveStringsW failed") return self._split_str_buf_list(buf, buf_len)
def enable_auto_recovery(enable): current_store = _get_current_bcd_store() success, = current_store.SetBooleanElement( BCDLIBRARY_BOOLEAN_AUTO_RECOVERY_ENABLED, enable) if not success: raise exception.CloudbaseInitException( "Cannot set boolean element: %s" % BCDLIBRARY_BOOLEAN_AUTO_RECOVERY_ENABLED)
def _get_credentials(self, shared_data): user_name = shared_data.get(constants.SHARED_DATA_USERNAME) if not user_name: raise exception.CloudbaseInitException( "Cannot execute plugin as the username has not been set in " "the plugins shared data") password = shared_data.get(constants.SHARED_DATA_PASSWORD) if not password: raise exception.CloudbaseInitException( "Cannot execute plugin as the password has not been set in the" " plugins shared data") # For security reasons unset the password in the shared_data # as it is currently not needed by other plugins shared_data[constants.SHARED_DATA_PASSWORD] = None return (user_name, password)
def _name2idx(name): """Get the position of a network interface by its name.""" match = re.search(r"eth(\d+)", name, re.I) if not match: raise exception.CloudbaseInitException( "invalid NetworkDetails name {!r}" .format(name) ) return int(match.group(1))
def get_physical_path(self): buf = ctypes.create_unicode_buffer(1024) bufLen = wintypes.DWORD(ctypes.sizeof(buf)) ret_val = virtdisk.GetVirtualDiskPhysicalPath(self._handle, ctypes.byref(bufLen), buf) if ret_val: raise exception.CloudbaseInitException( "Cannot get virtual disk physical path") return buf.value
def _get_user_info(self, username, level): try: return win32net.NetUserGetInfo(None, username, level) except win32net.error as ex: if ex.args[0] == self.NERR_UserNotFound: raise exception.ItemNotFoundException("User not found: %s" % username) else: raise exception.CloudbaseInitException( "Failed to get user info: %s" % ex.args[2])
def set_network_adapter_mtu(self, mac_address, mtu): if not self.check_os_version(6, 0): raise exception.CloudbaseInitException( 'Setting the MTU is currently not supported on Windows XP ' 'and Windows Server 2003') iface_index_list = [ net_addr["interface_index"] for net_addr in network.get_adapter_addresses() if net_addr["mac_address"] == mac_address ] if not iface_index_list: raise exception.CloudbaseInitException( 'Network interface with MAC address "%s" not found' % mac_address) else: iface_index = iface_index_list[0] LOG.debug( 'Setting MTU for interface "%(mac_address)s" with ' 'value "%(mtu)s"', { 'mac_address': mac_address, 'mtu': mtu }) base_dir = self._get_system_dir() netsh_path = os.path.join(base_dir, 'netsh.exe') args = [ netsh_path, "interface", "ipv4", "set", "subinterface", str(iface_index), "mtu=%s" % mtu, "store=persistent" ] (out, err, ret_val) = self.execute_process(args, shell=False) if ret_val: raise exception.CloudbaseInitException( 'Setting MTU for interface "%(mac_address)s" with ' 'value "%(mtu)s" failed' % { 'mac_address': mac_address, 'mtu': mtu })
def _get_timezone_info(self): keyname = os.path.join(REG_TIME_ZONES, self._name) try: with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, keyname) as key: return self._unpack_timezone_info(key) except WindowsError as exc: if exc.errno == NOT_FOUND: raise exception.CloudbaseInitException( "Timezone %r not found" % self._name) else: raise
def _get_goal_state(self, force_update=False): if not self._goal_state or force_update: self._goal_state = self._wire_server_request( "machine?comp=goalstate").GoalState expected_state = self._goal_state.Machine.ExpectedState if expected_state != GOAL_STATE_STARTED: raise exception.CloudbaseInitException( "Invalid machine expected state: %s" % expected_state) return self._goal_state
def change_password_next_logon(self, username): """Force the given user to change the password at next logon.""" user_info = self._get_user_info(username, 4) user_info["flags"] &= ~win32netcon.UF_DONT_EXPIRE_PASSWD user_info["password_expired"] = 1 try: win32net.NetUserSetInfo(None, username, 4, user_info) except win32net.error as ex: raise exception.CloudbaseInitException( "Setting password expiration failed: %s" % ex.args[2])
def open(self): if self._handle: self.close() handle = kernel32.CreateFileW(ctypes.c_wchar_p(self._path), self.GENERIC_READ, self.FILE_SHARE_READ, 0, self.OPEN_EXISTING, self.FILE_ATTRIBUTE_READONLY, 0) if handle == self.INVALID_HANDLE_VALUE: raise exception.CloudbaseInitException('Cannot open file') self._handle = handle
def _run_bcdedit(bcdedit_args): args = ["bcdedit.exe"] + bcdedit_args osutils = osutils_factory.get_os_utils() (out, err, ret_val) = osutils.execute_system32_process(args) if ret_val: raise exception.CloudbaseInitException( 'bcdedit failed.\nOutput: %(out)s\nError:' ' %(err)s' % { 'out': out, 'err': err })
def _socket_addr_to_str(socket_addr): addr_str_len = wintypes.DWORD(256) addr_str = ctypes.create_unicode_buffer(256) ret_val = ws2_32.WSAAddressToStringW(socket_addr.lpSockaddr, socket_addr.iSockaddrLength, None, addr_str, ctypes.byref(addr_str_len)) if ret_val: raise exception.CloudbaseInitException( "WSAAddressToStringW failed: %s" % ws2_32.WSAGetLastError()) return addr_str.value
def get_metadata_service(): # Return the first service that loads correctly cl = classloader.ClassLoader() for class_path in CONF.metadata_services: service = cl.load_class(class_path)() try: if service.load(): return service except Exception as ex: LOG.error("Failed to load metadata service '%s'" % class_path) LOG.exception(ex) raise exception.CloudbaseInitException("No available service found")
def _get_network_config_parser(self, parser_type): parsers = { self.NETWORK_LINK_TYPE_PHY: self._parse_physical_config_item, self.NETWORK_LINK_TYPE_BOND: self._parse_bond_config_item, self.NETWORK_LINK_TYPE_VLAN: self._parse_vlan_config_item, self.NETWORK_SERVICE_NAMESERVER: self._parse_nameserver_config_item } parser = parsers.get(parser_type) if not parser: raise exception.CloudbaseInitException( "Network config parser '%s' does not exist", parser_type) return parser
def create_user_logon_session(self, username, password, domain='.', load_profile=True): token = wintypes.HANDLE() ret_val = advapi32.LogonUserW(six.text_type(username), six.text_type(domain), six.text_type(password), 2, 0, ctypes.byref(token)) if not ret_val: raise exception.CloudbaseInitException("User logon failed") if load_profile: pi = Win32_PROFILEINFO() pi.dwSize = ctypes.sizeof(Win32_PROFILEINFO) pi.lpUserName = six.text_type(username) ret_val = userenv.LoadUserProfileW(token, ctypes.byref(pi)) if not ret_val: kernel32.CloseHandle(token) raise exception.CloudbaseInitException( "Cannot load user profile") return token
def set_ntp_client_config(self, ntp_host): base_dir = self._get_system_dir() w32tm_path = os.path.join(base_dir, "w32tm.exe") args = [w32tm_path, '/config', '/manualpeerlist:%s' % ntp_host, '/syncfromflags:manual', '/update'] (out, err, ret_val) = self.execute_process(args, False) if ret_val: raise exception.CloudbaseInitException( 'w32tm failed to configure NTP.\nOutput: %(out)s\nError:' ' %(err)s' % {'out': out, 'err': err})
def add_static_route(self, destination, mask, next_hop, interface_index, metric): if not isinstance(next_hop, six.text_type): next_hop = next_hop.decode('utf-8') args = ['ROUTE', 'ADD', destination, 'MASK', mask, next_hop] (out, err, ret_val) = self.execute_process(args) # Cannot use the return value to determine the outcome if ret_val or err: raise exception.CloudbaseInitException( 'Unable to add route: %s' % err)
def add_user_to_local_group(self, username, groupname): lmi = Win32_LOCALGROUP_MEMBERS_INFO_3() lmi.lgrmi3_domainandname = six.text_type(username) ret_val = netapi32.NetLocalGroupAddMembers(0, six.text_type(groupname), 3, ctypes.addressof(lmi), 1) if ret_val == self.NERR_GroupNotFound: raise exception.CloudbaseInitException('Group not found') elif ret_val == self.ERROR_ACCESS_DENIED: raise exception.CloudbaseInitException('Access denied') elif ret_val == self.ERROR_NO_SUCH_MEMBER: raise exception.CloudbaseInitException('Username not found') elif ret_val == self.ERROR_MEMBER_IN_ALIAS: # The user is already a member of the group pass elif ret_val == self.ERROR_INVALID_MEMBER: raise exception.CloudbaseInitException('Invalid user') elif ret_val != 0: raise exception.CloudbaseInitException('Unknown error')
def _delete_static_route(self, network): """Delete a route from the operating system.""" try: osutils = osutils_factory.get_os_utils() LOG.debug('Deleting route for network: %s', network) args = ['ROUTE', 'DELETE', network] (out, err, ret_val) = osutils.execute_process(args) if ret_val or err: raise exception.CloudbaseInitException( 'Failed to delete route: %s' % err) except Exception as ex: LOG.exception(ex)
def _extract_files_from_iso(self, iso_file_path): args = [CONF.bsdtar_path, '-xf', iso_file_path, '-C', self.target_path] (out, err, exit_code) = self._osutils.execute_process(args, False) if exit_code: raise exception.CloudbaseInitException( 'Failed to execute "bsdtar" from path "%(bsdtar_path)s" with ' 'exit code: %(exit_code)s\n%(out)s\n%(err)s' % { 'bsdtar_path': CONF.bsdtar_path, 'exit_code': exit_code, 'out': out, 'err': err})
def set_static_network_config(self, mac_address, address, netmask, broadcast, gateway, dnsnameservers): conn = wmi.WMI(moniker='//./root/cimv2') query = conn.query("SELECT * FROM Win32_NetworkAdapter WHERE " "MACAddress = '{}'".format(mac_address)) if not len(query): raise exception.CloudbaseInitException( "Network adapter not found") adapter_config = query[0].associators( wmi_result_class='Win32_NetworkAdapterConfiguration')[0] LOG.debug("Setting static IP address") (ret_val,) = adapter_config.EnableStatic([address], [netmask]) if ret_val > 1: raise exception.CloudbaseInitException( "Cannot set static IP address on network adapter (%d)", ret_val) reboot_required = (ret_val == 1) if gateway: LOG.debug("Setting static gateways") (ret_val,) = adapter_config.SetGateways([gateway], [1]) if ret_val > 1: raise exception.CloudbaseInitException( "Cannot set gateway on network adapter (%d)", ret_val) reboot_required = reboot_required or ret_val == 1 if dnsnameservers: LOG.debug("Setting static DNS servers") (ret_val,) = adapter_config.SetDNSServerSearchOrder(dnsnameservers) if ret_val > 1: raise exception.CloudbaseInitException( "Cannot set DNS on network adapter (%d)", ret_val) reboot_required = reboot_required or ret_val == 1 return reboot_required
def _preprocess_options(self): self._searched_types = set(CONF.config_drive_types) self._searched_locations = set(CONF.config_drive_locations) # Deprecation backward compatibility. if CONF.config_drive_raw_hhd: self._searched_types.add("iso") self._searched_locations.add("hdd") if CONF.config_drive_cdrom: self._searched_types.add("iso") self._searched_locations.add("cdrom") if CONF.config_drive_vfat: self._searched_types.add("vfat") self._searched_locations.add("hdd") # Check for invalid option values. if self._searched_types | CD_TYPES != CD_TYPES: raise exception.CloudbaseInitException( "Invalid Config Drive types %s", self._searched_types) if self._searched_locations | CD_LOCATIONS != CD_LOCATIONS: raise exception.CloudbaseInitException( "Invalid Config Drive locations %s", self._searched_locations)
def get_geometry(self): if not self._geom: geom = Win32_DiskGeometry() bytes_returned = wintypes.DWORD() ret_val = kernel32.DeviceIoControl( self._handle, self.IOCTL_DISK_GET_DRIVE_GEOMETRY, 0, 0, ctypes.byref(geom), ctypes.sizeof(geom), ctypes.byref(bytes_returned), 0) if not ret_val: raise exception.CloudbaseInitException( "Cannot get disk geometry") self._geom = geom return self._geom
def _get_credentials(service, shared_data): user_name = shared_data.get(constants.SHARED_DATA_USERNAME, CONF.username) if not user_name: raise exception.CloudbaseInitException( "Cannot execute plugin as the username has not been set in " "the plugins shared data, nor it was found in config file.") password = shared_data.get(constants.SHARED_DATA_PASSWORD) if not password: password = service.get_admin_password() if not password: raise exception.CloudbaseInitException( "Cannot execute plugin as the password has not been set " "in the plugins shared data, nor it was retrieved " "from the metadata service.") # For security reasons unset the password in the shared_data # as it is currently not needed by other plugins shared_data[constants.SHARED_DATA_PASSWORD] = None return user_name, password